2017-03-15 6 views
0

私はおそらくここで明らかに何か愚かなことをしています。それを指摘してください!GZipStreamを使ってメモリ内のgzファイルをどのように解凍しますか?

私はSFTPから(。SSH.NET Nuget packageを使用して素晴らしい!)複数の.gzファイルをプルダウンしているC#コードをいくつか持っています。各gzには、その中に1つの.CSVファイルしか含まれていません。私はこれらのファイルをディスクに入れずにメモリに保存したいと思います(これらのファイルはかなり小さいため、サーバーのメモリ管理の問題はあります)。メモリ内で解凍して内部のCSVファイルを抽出し、カスタムDTO(FtpFile)のCSVファイル

私の問題は、SFTP接続のMemoryStreamにデータが入っているうちに、GZipStreamにデータが埋め込まれていないか、GZipStreamから出力されたMemoryStreamへのコピーが失敗していることです。私は自分のバッファでReadよりももっと伝統的なループを試みましたが、このコードと同じ結果でした。接続の詳細は別に

(それが正常に接続するので、そこに何の心配もなく)、ここに私のコードのすべてです:「

public static List<FtpFile> Foo() 
    { 
     var connectionInfo = new ConnectionInfo("example.com", 
      "username", 
      new PasswordAuthenticationMethod("username", "password")); 
     using (var client = new SftpClient(connectionInfo)) 
     { 
      client.Connect(); 

      var searchResults = client.ListDirectory("/testdir") 
       .Where(obj => obj.IsRegularFile 
           && obj.Name.ToLowerInvariant().StartsWith("test_") 
           && obj.Name.ToLowerInvariant().EndsWith(".gz")) 
       .Take(2) 
       .ToList(); 

      var fileResults = new List<FtpFile>(); 

      foreach (var file in searchResults) 
      { 
       var ftpFile = new FtpFile { FileName = file.Name, FileSize = file.Length }; 

       using (var fileStream = new MemoryStream()) 
       { 
        client.DownloadFile(file.FullName, fileStream); // Success! All is good here, so far. :) 

        using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress)) 
        { 
         using (var outputStream = new MemoryStream()) 
         { 
          gzStream.CopyTo(outputStream); 
          byte[] outputBytes = outputStream.ToArray(); // No data. Sad panda. :'(
          ftpFile.FileContents = Encoding.ASCII.GetString(outputBytes); 
          fileResults.Add(ftpFile); 
         } 
        } 
       } 
      } 

      return fileResults; 
     } 
    } 

FTPFILE(単純なDTO I:

ロジック m個の移入):

public class FtpFile 
{ 
    public string FileName { get; set; } 
    public long FileSize { get; set; } 
    public string FileContents { get; set; } 
} 

PSA誰かがこのコードをコピーした場合、このコードではという深刻なメモリ管理の問題がある可能性があるという点で、これは良いコードではないことに注意してください。代わりに、でなく、がこのコードで実行されていることをディスクにストリームすることをお勧めします。私のニーズは、私がそれらで構築しているもののためにこれらのファイルを同時にメモリ内に持っていなければならないという点で非常に特有です。

+0

は、有効なGZIP形式の値はありますか? gzippedバイト[]をチェックすると、長さが10で、次のシーケンスが31,139,8,0,0,0,0,0,4,0の場合にチェックされます。これは、適切にgzipされていないことを意味します。 – StfBln

+0

@StfBln GZipped値の長さは1884で、このシーケンスで始まる:31,139,8,0,120,192,198,88。また、これはサードパーティのプロダクションシステムからのもので、これまでの初期テストではこれらのgzファイルで手動で作業することに問題はありませんでした。 – Jaxidian

+1

"client.DownloadFile(file.FullName、fileStream)"はストリームを巻き戻しますか?そうでなければfileStreamを "Seek(0、SeekOrigin.Begin)"を使用して巻き戻す必要があります – StfBln

答えて

1

ストリームにデータを挿入する場合は、ストリームを元に戻してから、ジグザグを解除してください。

次はあなたの悩みを解決する必要があります。

  using (var fileStream = new MemoryStream()) 
      { 
       client.DownloadFile(file.FullName, fileStream); // Success! All is good here, so far. :) 
       fileStream.Seek(0, SeekOrigin.Begin); 

       using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress)) 
       { 
        using (var outputStream = new MemoryStream()) 
        { 
         gzStream.CopyTo(outputStream); 
         byte[] outputBytes = outputStream.ToArray(); // No data. Sad panda. :'(
         ftpFile.FileContents = Encoding.ASCII.GetString(outputBytes); 
         fileResults.Add(ftpFile); 
        } 
       } 
      } 
+0

それだけです!ありがとうございました!!これは 'fileStream.Position = 0;'と同じですか、それとも両者が違うのでしょうか? – Jaxidian

+1

@Jaxidian fileStream.Position = 0;うまくいくはずです。詳細については、http://stackoverflow.com/questions/7238929/stream-seek0-seekorigin-begin-or-position-0を参照してください。 – StfBln

+0

もう一度ありがとう! :-) – Jaxidian

関連する問題