如何使用GZipStream解压缩内存中的gz文件?
问题描述:
我可能在这里做一些明显愚蠢的事情。请指出!如何使用GZipStream解压缩内存中的gz文件?
我有一些C#代码是从SFTP下拉一堆.gz文件(使用SSH.NET Nuget package - 效果很好!)。每个gz在其中只包含一个.CSV文件。我想将这些文件保存在内存中而不会触及磁盘(是的,我知道存在服务器内存管理问题 - 这些文件相当小),在内存中解压缩以提取CSV文件,然后返回自定义DTO中的CSV文件(FtpFile
)。
我的问题是,虽然我从SFTP连接的MemoryStream中有数据,但它似乎没有填充在我的GZipStream中,或者从GZipStream复制到我的输出MemoryStream失败。我已经尝试了使用我自己的缓冲区读取更传统的循环,但它具有与此代码相同的结果。
从连接细节除了(连接成功,所以不用担心有),这里是我的全部代码:
逻辑:
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我”米填充):
public class FtpFile
{
public string FileName { get; set; }
public long FileSize { get; set; }
public string FileContents { get; set; }
}
PSA如果有人来复制此代码,请注意,这是不好的代码,你可能有一些严重这个代码的内存管理问题!这是最好的做法,而不是流到磁盘,这是而不是正在执行此代码!我的需求非常具体,因为我必须将这些文件同时存储在内存中,以便与我一起构建它们。
答
如果您要将数据插入流中,请务必在解压缩数据之前找回其来源。
下应解决您的烦恼:
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);
}
}
}
是gzip压缩值是否有效?如果你检查gzip字节[],如果它的长度为10,并且具有以下序列:31,139,8,0,0,0,0,0,4,0。这意味着它没有被正确地压缩。 – StfBln
@StfBln GZipped值的长度为1884,从该序列开始:31,139,8,0,120,192,198,88。此外,这是来自第三方生产系统,迄今为止我们在初始测试中手动处理这些gz文件没有问题。 – Jaxidian
“client.DownloadFile(file.FullName,fileStream)”是否倒回流?否则fileStream需要使用“Seek(0,SeekOrigin.Begin)” – StfBln