본문 바로가기

Windows Phone 7

Windows Phone 7 에서 ZIP 압축파일 읽기

이번에는 Windows Phone 7에서 압축파일에서 개별 파일을 읽는 방법에 대해서 알아보고자 합니다.
Silverlight 기반의 Windows Phone 7 응용프로그램의 배포에 사용되는 XAP 파일이 ZIP형식의 압축파일입니다.
C# 코드가 컴파일되어 있는 DLL과 XAML 파일, 리소스들이 이 압축파일에 포함되어 있죠.
그러니, 분명히 Windows Phone에서는 ZIP 압축파일을 해제하는 방법이 분명히 존재합니다.
하지만, 그 부분은 제공하는 API가 아무래도 좀 빈약하고, ZIP의 압축이나 압축해제의 용도로만 사용되는 것이 아니다 보니, 용도에 딱 들어맞지 않을 수 밖에 없습니다.

그래서, 오픈소스로 제공되고 있는 SharpZipLib을 이용하는 방법이 없을까하고 생각하던 중에, Nick's .NET Travels :: Windows Phone 7 Data : Json WCF Data Service with IIS7 Compression 이라는 블로그 글에서 SharpZipLib을 WP7 용으로 컨버팅해서 제공하는 발견하고 얼른 받아서 구현해봤습니다.

SharpZipLib for Windows Phone : 다운로드

이번 샘플은 다수의 이미지 파일을 포함한 압축파일(ZIP)에서 이미지 파일을 추출하여 보여주는 형태로 만들었습니다.

아래 샘플소스는 Windows Phone Developer Tools Beta 를 이용하여 만들어 졌으며, RTM 버전에서의 테스트도 완료되었습니다.


압축된 이미지파일 보여주기 샘플 구현
  1. 새로운 Windows Phone Application 프로젝트를 생성합니다.
  2. Solution Explorer에서 솔루션을 선택하고 Add - Existing Project...를 선택하여 다운로드 받은 파일에서 wpICSharpCode.SharpZLib.csproj 를 선택하여 프로젝트를 추가합니다.
  3. Windows Phone Application 프로젝트에서 Add Reference 를 선택하고, 추가한 Projects 탭에서 wpICSharpCode.SharpZLib 을 추가해 주세요.

  4. 이미지 파일들로 구성된 압축파일을 Window Phone Application 프로젝트에 추가하고, Properties 창에서 Build ActionContent 로 변경하여 주십시오.


  5. MainPage.xaml 의 UI는 아래와 같이 구성하였습니다.


  6. 이제 PhoneApplicationPage 의 Loaded 이벤트와 prevButton 그리고 nextButton 버튼의 Clicked 이벤트에 각각의 이벤트 핸들러를 등록하여 주십시오.
  7. 클래스 멤버변수로 압축파일의 정보를 보관할 ISharpCode.SharpzipLib.Zip 네임스페이스의 ZipFile 클래스와 현재 이미지 파일의 인덱스를 관리할 Int32형식의 변수를 선언합니다.


    public
    partial class MainPage : PhoneApplicationPage

    {

        ZipFile _zipfile = null;

        int _fileIndex = -1;


  8. 페이지가 로드되면 리소스 파일로 첨부한 SamplePictures.zip 파일을 이용하여 ZipFile 클래스의 인스턴스를 생성하고 로드시에 첫 페이지를 출력할 수 있도록 합니다.

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

    {

        StreamResourceInfo zipStreamResource = Application.GetResourceStream(
                                                  new
    Uri("SamplePictures.zip", UriKind.Relative));

        _zipfile = new ZipFile(zipStreamResource.Stream);

     

        MoveNextImage();

    }


    위 코드에서 ZipFile 클래스의 인스턴스를 생성하기 위하여 Stream 을 이용하는 것을 알 수 있습니다. 우리는 압축파일을 리소스 형태로 추가하였으므로, StreamResourceInfo 객체에서 Stream 객체를 획득할 수 있습니다.
    만일, 격리된 저장소에 파일이 존재한다면, 이전 포스트인 [Windows Phone 7] - 웹에서 Windows Phone 7의 격리된 저장소로 파일 다운로드 받기 에 격리된 저장소에서 파일 읽는 방법이 구현되어 있으므로 참고하시기 바랍니다.

  9. 가장 핵심이라고 할 수 있는 압축(ZIP)파일에서 이미지를 읽어오는 코드를 포함할 ViewImage라는 메서드를 생성하고 아래와 같이 구현합니다.

    private void ViewImage()

    {

        ZipEntry entry = _zipfile[_fileIndex];

        String entryFileName = entry.Name;

        using (Stream zipStream = _zipfile.GetInputStream(entry))

        {

            byte[] buffer = new byte[4096];

            int readBytes;

            using (MemoryStream mStream = new MemoryStream())

            {

                do

                {

                    readBytes = zipStream.Read(buffer, 0, buffer.Length);

                    mStream.Write(buffer, 0, readBytes);

     

                } while (readBytes > 0);

     

                BitmapImage image = new BitmapImage();

                image.SetSource(mStream);

                contentImage.Source = image;

     

                mStream.Close();

            }

     

            zipStream.Close();

        }

    }


    ZipFile 객체에서 현재 인덱스의 파일을 가져오면 ZipEntry 클래스의 객체를 가져올 수 있으며, 이 ZipEntry 객체의 GetInputStream을 이용하여 압축되어 있는 파일의 스트림을 획득할 수 있습니다.
    하지만, 주의할 점은 현재 획득한 스트림을 이용하여 바로 BitmapImage 객체를 생성할 수가 없습니다.
    이를 위해 코드에서는 MemoryStream에 압축 파일의 스트림을 기록하여 BitmapImage 객체를 생성하고 있습니다.
    그리고, 생성한 BitmapImage 객체를 contentImage 컨트롤에 소스로 등록하여 이미지를 출력합니다.

  10. 압축 파일에는 다수의 이미지가 존재하므로 전후로 이동하기 위해서 아래와 같은 코드를 등록합니다.

    private void MoveNextImage()

    {

        if (_fileIndex + 1 < _zipfile.Count)

        {

            _fileIndex++;

            ViewImage();

        }

    }

     

    private void MovePrevImage()

    {

        if (_fileIndex - 1 >= 0)

        {

            _fileIndex--;

            ViewImage();

        }

    }


    ZipFile 객체에서 Count 속성을 통해 압축파일내에 있는 파일의 갯수를 알 수 있습니다

  11. 마지막으로 prevButton 와 nextButton 버튼 컨트롤의 Click 이벤트 핸들러를 추가합니다.

    private void nextButton_Click(object sender, RoutedEventArgs e)

    {

        MoveNextImage();

    }

     

    private void prevButton_Click(object sender, RoutedEventArgs e)

    {

        MovePrevImage();

    }


  12. 프로젝트를 실행하면 압축파일에 포함된 이미지가 출력됨을 알 수 있습니다.
    또한 버튼을 이용하여 다음 이미지 및 이전 이미지로의 이동이 가능합니다.
만일 실행 시에 PlatformNotSupportedException 이 발생한다면, wpICSharpCode.SharpZLib 프로젝트에서 Zip 폴더내의 ZipConstraints.cs 파일에서


Encoding.GetEncoding(DefaultCodePage)


부분을 아래와 같이 변경하여 주십시오.


Encoding.UTF8


이는 현재 Windows Phone 7 에서는 Encoding 이 UTF-8 만을 지원하므로, 다른 형식의 인코딩을 이용하고자 하여 발생하는 문제입니다.
한국어가 지원되는 Windows Phone 7 이 나올때 쯤이면 이 문제도 해결되지 않을까 생각합니다.


샘플 프로젝트 파일을 따로 올렸으니 참고하시기 바랍니다.
첨부된 파일에는 업로드 용량관계로 압축파일이 포함되어 있지 않으니, 압축파일을 추가하여 사용하시면 됩니다.

격리된 저장소에서 Zip파일을 읽어 오실경우에는 [Windows Phone 7] - Windows Phone 7에서 격리된 저장소의 압축파일을 SharpZipLib 활용하여 읽기(AS) 를 확인하여 주십시오.


끝까지 읽어 주셔서 감사합니다.

그럼 좋은 하루 되십시오.