53

エントリが 1 つのコードから新しい ZIP パッケージを作成し、その ZIP パッケージをファイルに保存しようとしています。System.IO.Compression.ZipArchiveクラスでこれを達成しようとしています。次のコードで ZIP パッケージを作成しています。

using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine(
                "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }

次に、ZIP を WinRT のいずれかのファイルに保存します。

        var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip", CreationCollisionOption.ReplaceExisting);
        zipStream.Position = 0;
        using (Stream s = await file.OpenStreamForWriteAsync())
        {
            zipStream.CopyTo(s);
        }

または、通常の .NET 4.5 では:

        using (FileStream fs = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
        {
            zipStream.Position = 0;
            zipStream.CopyTo(fs);
        }

しかし、生成されたファイルは Windows エクスプローラーや WinRAR などでも開くことができません (生成されたファイルのサイズが zipStream の長さと一致することを確認したので、ストリーム自体は正しくファイルに保存されました)
。何か間違ったことをしているのですか、それとも ZipArchive クラスに問題がありますか?

4

6 に答える 6

107

私は自分のコードに (後から考えると明らかな) エラーを見つけました。ZipArchive を破棄してその内容を基になるストリームに書き込む必要があります。そのため、ZipArchive の using ブロックの終了後にストリームをファイルに保存する必要がありました。また、コンストラクターのleaveOpen引数を true に
設定して、基になるストリームを閉じないようにすることが重要でした。したがって、完全な実用的なソリューションは次のとおりです。

using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine(
                "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }
    }

    var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
        "test.zip",
        CreationCollisionOption.ReplaceExisting);

    zipStream.Position = 0;
    using (Stream s = await file.OpenStreamForWriteAsync())
    {
        zipStream.CopyTo(s);
    }
}
于 2012-09-10T10:48:30.647 に答える
4

すべてのストリーム オブジェクトで、.Seek メソッドを使用して他のアプリケーションが正しく読み取れるように、最初からストリームを巻き戻す必要があります。

例:

zipStream.Seek(0, SeekOrigin.Begin);
于 2012-09-10T08:24:55.537 に答える
1

ソースのようなファイルストリームを使用して、逆の順序でのみ同じ考え方に従うことができます。以下のフォームを実行したところ、ファイルは正常に開かれました。

string fileFormat = ".zip"; // any format
string filename = "teste" + fileformat;

StorageFile zipFile = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename,CreationCollisionOption.ReplaceExisting);

using (Stream zipStream = await zipFile.OpenStreamForWriteAsync()){

   using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create)){
        //Include your content here
   }
}
于 2013-02-28T21:43:52.947 に答える
0

完全なコードは次のようになります。

var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("test.zip",CreationCollisionOption.ReplaceExisting);
using (Stream zipStream = await zipFile.OpenStreamForWriteAsync())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine("Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }
    }   
}
于 2013-02-28T21:48:53.727 に答える