使用GZipStream如何在内存中解压缩一个gz文件?

7 浏览
0 Comments

使用GZipStream如何在内存中解压缩一个gz文件?

我这里可能在做一些明显愚蠢的事情,请指出来!我有一些C#代码,从SFTP(使用SSH.NET Nuget package - 运行得很好!)中下载一堆.gz文件。每个gz文件中只包含一个.CSV文件。我想将这些文件保存在内存中,而不是在磁盘上(是的,我知道,存在服务器内存管理问题 - 对于这些文件来说没问题,因为它们相当小),在内存中解压缩它们以提取其中的CSV文件,然后返回一个自定义DTO(FtpFile)的CSV文件集合。

我的问题是,虽然我从SFTP连接的MemoryStream中有数据,但无论是它似乎从未在我的GZipStream中填充,还是从GZipStream复制到我的输出MemoryStream失败。我尝试过使用更传统的循环读取自己的缓冲区,但结果与此代码相同。

除了连接详细信息(连接成功,所以不用担心),这是我的所有代码:

逻辑代码

public static List 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();
        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 如果有人复制此代码,请注意这不是好的代码,因为您可能会在此代码中遇到一些严重的内存管理问题!最佳实践是将其流式传输到磁盘,而这在此代码中实现!我的需求非常特殊,因为我必须同时在内存中拥有这些文件,以便构建它们。

0
0 Comments

如何在内存中解压缩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/…以获取更多信息。

再次感谢!:-)

0