使用GZipStream如何在内存中解压缩一个gz文件?
使用GZipStream如何在内存中解压缩一个gz文件?
我这里可能在做一些明显愚蠢的事情,请指出来!我有一些C#代码,从SFTP(使用SSH.NET Nuget package - 运行得很好!)中下载一堆.gz文件。每个gz文件中只包含一个.CSV文件。我想将这些文件保存在内存中,而不是在磁盘上(是的,我知道,存在服务器内存管理问题 - 对于这些文件来说没问题,因为它们相当小),在内存中解压缩它们以提取其中的CSV文件,然后返回一个自定义DTO(FtpFile
)的CSV文件集合。
我的问题是,虽然我从SFTP连接的MemoryStream中有数据,但无论是它似乎从未在我的GZipStream中填充,还是从GZipStream复制到我的输出MemoryStream失败。我尝试过使用更传统的循环读取自己的缓冲区,但结果与此代码相同。
除了连接详细信息(连接成功,所以不用担心),这是我的所有代码:
逻辑代码:
public static ListFoo() { 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 (); 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); // 成功!到目前为止一切都很好。 :) using (var gzStream = new GZipStream(fileStream, CompressionMode.Decompress)) { using (var outputStream = new MemoryStream()) { gzStream.CopyTo(outputStream); byte[] outputBytes = outputStream.ToArray(); // 没有数据。伤心的熊猫。 :'( ftpFile.FileContents = Encoding.ASCII.GetString(outputBytes); fileResults.Add(ftpFile); } } } } return fileResults; } }
FtpFile(只是一个简单的DTO):
public class FtpFile { public string FileName { get; set; } public long FileSize { get; set; } public string FileContents { get; set; } }
PSA 如果有人复制此代码,请注意这不是好的代码,因为您可能会在此代码中遇到一些严重的内存管理问题!最佳实践是将其流式传输到磁盘,而这在此代码中未实现!我的需求非常特殊,因为我必须同时在内存中拥有这些文件,以便构建它们。
如何在内存中解压缩gz文件使用GZipStream?
问题的原因是如果您要将数据插入流中,请确保在解压缩之前将其指针定位回原始位置。
解决方法如下:
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); } } }
就是这样!谢谢!这与fileStream.Position = 0;
是一样的吗?还是两者有所不同?
fileStream.Position = 0;
也可以工作。参见stackoverflow.com/questions/7238929/…以获取更多信息。
再次感谢!:-)