ストリームの流れがあります。"checksum"を一連の.zipファイルで計算します。Observable。破損したデータを取得しているストリームを使用しています。
はそれを行うには、私が観察できるように設定している :
- が
- は、各ファイルの内容を読み込み、指定したフォルダ内のすべてのファイルを受け取り、各エントリの
- (
ZipArchive
として読んで)各ファイルには、
はそれを説明するためにチェックサムの計算を行い、私はこの例を作成しました十分な:
NOTICE Main
方法を作るためにAsyncContext.Run
(https://stackoverflow.com/a/9212343/1025407)の使用量がGetChecksum
を待って、それはアプリケーションを実行するコンソールアプリケーション
namespace DisposePoC
{
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Reactive.Linq;
using Nito.AsyncEx;
using System.Linq;
using System.Threading.Tasks;
class Program
{
private static void Main()
{
AsyncContext.Run(GetChecksums);
}
private static async Task<IList<byte>> GetChecksums()
{
var bytes = Directory.EnumerateFiles("FolderWithZips")
.ToObservable()
.SelectMany(path => Observable.Using(() => CreateZipArchive(path), archive => archive.Entries.ToObservable()))
.SelectMany(entry => Observable.Using(entry.Open, stream => Observable.FromAsync(() => CalculateChecksum(stream, entry.Length))));
return await bytes.ToList();
}
private static ZipArchive CreateZipArchive(string path)
{
return new ZipArchive(new FileStream(path, FileMode.Open, FileAccess.Read));
}
private static async Task<byte> CalculateChecksum(Stream stream, long entryLength)
{
var bytes = await GetBytesFromStream(stream, entryLength);
return bytes.Aggregate((b1, b2) => (byte) (b1^b2));
}
private static async Task<byte[]> GetBytesFromStream(Stream stream, long entryLength)
{
byte[] bytes = new byte[entryLength];
await stream.ReadAsync(bytes, 0, (int)entryLength);
return bytes;
}
}
}
なので、私はエラーのすべての種類を取得:
'System.IO.InvalidDataException':ローカルファイルヘッダーが破損しています。 'System.NotSupportedException':ストリームは読み取りをサポートしていません。 'System.ObjectDisposedException':配置されたオブジェクトにアクセスできません。 'System.IO.InvalidDataException':ブロックの長さがその補数と一致しません。
私は間違っていますか?
observable自体に問題はありますか?ZipArchive
はスレッドセーフではないためですか?そうでない場合は、コードをどのように動作させるのですか?
私は、現時点では中・コードを確認することができないので、私はこのコメント作ってあげるが、私は、問題が最初にSelectManyで作成されてZipArchivesは、Usingステートメントによって処分されていることである疑いがあるでしょう次の行の入力ストリームを読む前に、本質的に、使い捨てのスコープは間違っています。私は2番目のSelectManyから最初のロジックにロジックを移動します。最初の例外が示すように、テストデータが破損していないことを確認します。 – Andrew
私はあなたの意見を見ると思います。しかし、範囲が間違っている場合、すべてのエントリーが処理されるまで各ZipArchiveの処分を避けるためにコードを修正する必要がありますか?それも可能ですか? – SuperJMN