C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[7]: .NET 4.5でZipArciveクラスを使いたい


(過去ログ 136 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■79975 / inTopicNo.1)  .NET 4.5でZipArciveクラスを使いたい
  
□投稿者/ hide (1回)-(2016/06/02(Thu) 16:12:20)

分類:[C#] 

初めて質問します。

.NET Framework 4.5環境で、ZipArchiveクラスによるアーカイブ作成を行って見たのですが、出来上がるzipファイルが不正な物になってしまいます。
サンプル実装は以下の通りです。

FileStream fs=new FileStream( "c:\\temp\\test.zip",FileMode.Create ,FileAccess.Write );
ZipArchive arc=new ZipArchive( fs , ZipArchiveMode.Create );
foreach( string filename in Directory.GetFiles("c:\\" ) ) {
	ZipArchiveEntry entry = arc.CreateEntry( System.IO.Path.GetFileName(  filename ) ) ; 
	Stream stEntry=entry.Open();
	System.IO.FileStream fsRead = new FileStream( filename , FileMode.Open, FileAccess.Read);
	fsRead.CopyTo( stEntry );
	fsRead.Close();
	stEntry.Close();
}

上記実装にて、ファイルが格納されたZIPファイルは出来上がるのですが、何故かZIP内の各ファイルのCRC値がすべてゼロになってしまいます。結果、そのままでは「ファイルが壊れている」として展開できません。
ただし、出来上がったZIPファイルをWinZipを使って「修復」すればCRCが入り、普通に展開できるようになります。もちろん展開されたファイルにも異常は見受けられません。

どうしてこういう動作になるか、ご存知の方は居られませんでしょうか。


引用返信 編集キー/
■79977 / inTopicNo.2)  Re[1]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ とっちゃん (368回)-(2016/06/02(Thu) 16:29:16)
No79975 (hide さん) に返信
> 初めて質問します。
>
> .NET Framework 4.5環境で、ZipArchiveクラスによるアーカイブ作成を行って見たのですが、出来上がるzipファイルが不正な物になってしまいます。
> サンプル実装は以下の通りです。
>
> FileStream fs=new FileStream( "c:\\temp\\test.zip",FileMode.Create ,FileAccess.Write );
> ZipArchive arc=new ZipArchive( fs , ZipArchiveMode.Create );
> foreach( string filename in Directory.GetFiles("c:\\" ) ) {
> ZipArchiveEntry entry = arc.CreateEntry( System.IO.Path.GetFileName( filename ) ) ;
> Stream stEntry=entry.Open();
> System.IO.FileStream fsRead = new FileStream( filename , FileMode.Open, FileAccess.Read);
> fsRead.CopyTo( stEntry );
> fsRead.Close();
> stEntry.Close();
> }
>
> 上記実装にて、ファイルが格納されたZIPファイルは出来上がるのですが、何故かZIP内の各ファイルのCRC値がすべてゼロになってしまいます。結果、そのままでは「ファイルが壊れている」として展開できません。
> ただし、出来上がったZIPファイルをWinZipを使って「修復」すればCRCが入り、普通に展開できるようになります。もちろん展開されたファイルにも異常は見受けられません。
>
> どうしてこういう動作になるか、ご存知の方は居られませんでしょうか。
>
>
C:\ を対象にしているからなんてことはないですよね?

現在の Windows では、ルートディレクトリを対象に何かを行うということは一般的には行いません。
というか、MS-DOSの時代にまでさかのぼっても、ルートディレクトリのファイルを操作するのは、
一部のシステム設定用のファイル(CONFIG.SYS と AUTOEXEC.BAT)くらいで通常のデータファイルや各種
プログラム類は、サブディレクトリを用意するのが一般的だと思います。

ま、それはともかくとして、

CreaterEntryFromFile 拡張メソッドではダメですか?

具体的には、
foreach の中を

arc.CreateEntryFromFile( filename, SYstem.IO.Path.GetFileName( filename ) );

の1行に置き換えるだけです。

引用返信 編集キー/
■79979 / inTopicNo.3)  Re[2]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ hide (2回)-(2016/06/02(Thu) 16:41:48)
とっちゃんさん、ご回答ありがとうございます。

>C:\ を対象にしているからなんてことはないですよね?

これは質問用サンプルとして単純化しただけです。本来は別の場所からのアーカイブ作成を行っていますが、その場合とこのサンプルの場合で結果に変化はありませんでした。

>CreaterEntryFromFile 拡張メソッドではダメですか?

すいません、最終的にはメモリストリームによる実体ファイル無しの圧縮を実装するつもりなので、CreaterEntryFromFileでは目的に合致しません。


引用返信 編集キー/
■79980 / inTopicNo.4)  Re[3]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ hide (3回)-(2016/06/02(Thu) 16:50:39)
一応、CreaterEntryFromFileによる実装も試して見ましたが、こちらでもCRCはゼロになってしまいました。
一体どういう事なんでしょうか・・・・。
引用返信 編集キー/
■79981 / inTopicNo.5)  Re[4]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ hide (4回)-(2016/06/02(Thu) 17:00:36)
一応、自己解決しました。

全ファイルの書き込み完了後、ZipArchiveのインスタンスをDispose()してあげると、出来上がるZIP内にCRC値が正しく設定されました。
ネットで探したサンプルではそんな実装は見当たらなかったんですが・・・。
解決済み
引用返信 編集キー/
■79982 / inTopicNo.6)  Re[5]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ WebSurfer (925回)-(2016/06/02(Thu) 17:13:15)
No79981 (hide さん) に返信

> 全ファイルの書き込み完了後、ZipArchiveのインスタンスをDispose()してあげると、出来上がるZIP内にCRC値が正しく設定されました。
> ネットで探したサンプルではそんな実装は見当たらなかったんですが・・・。

MSDN ライブラリのサンプルコードを見ると using 句を使って Dispose するような実装になっていますが?

ZipArchive クラス
https://msdn.microsoft.com/ja-jp/library/system.io.compression.ziparchive(v=vs.110).aspx
解決済み
引用返信 編集キー/
■79983 / inTopicNo.7)  Re[6]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ hide (5回)-(2016/06/02(Thu) 17:34:56)
>using 句を使って Dispose するような実装になっていますが?

そうか!そういえばusing抜ければDisposeしますよね
間抜けな見落としでした(^^;

引用返信 編集キー/
■79984 / inTopicNo.8)  Re[7]: .NET 4.5でZipArciveクラスを使いたい
□投稿者/ とっちゃん (369回)-(2016/06/02(Thu) 18:44:44)
No79983 (hide さん) に返信
> >using 句を使って Dispose するような実装になっていますが?
> 
> そうか!そういえばusing抜ければDisposeしますよね
> 間抜けな見落としでした(^^;
>
自己解決しちゃったので、書かなかったのですが、検証したときに書き直したコードです。
記念パピコ程度に置いておきます。

using( FileStream fs=new FileStream( "c:\\temp\\test.zip",FileMode.Create ,FileAccess.Write ) )
using( ZipArchive arc=new ZipArchive( fs , ZipArchiveMode.Create ) )
{
	foreach( string filename in Directory.GetFiles("c:\\" ) ) {
		ZipArchiveEntry entry = arc.CreateEntry( System.IO.Path.GetFileName(  filename ) ) ; 
		using( Stream stEntry=entry.Open() )
		using( System.IO.FileStream fsRead = new FileStream( filename , FileMode.Open, FileAccess.Read) )
		{
			fsRead.CopyTo( stEntry );
		}
	}
}

ついでに、解決済みなので再チェックw

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -