我正在尝试通过WCF(部分GB)发送大量数据。我想在使用Streams读取文件时压缩文件,但看起来像DeflateStream有两种模式:
这些模式都不适用于我的情况。我想从磁盘读取一个未压缩的文件,并通过WCF返回一个压缩流。
有没有办法这样做,或者我必须使用临时文件(或MemoryStream)?
是否缺少功能或因某些原因无法使用?
答案 0 :(得分:3)
看起来你正在尝试在阅读文件时进行压缩。写入deflatestream的方式,压缩必须作为写入的一部分发生。尝试包装您通过网络发送的流,而不是您从磁盘读取的流。如果它们相同,则需要一个中间流。
答案 1 :(得分:3)
尝试使用这些方法压缩和解压缩字节数组。
private static byte[] Compress(byte[] data)
{
byte[] retVal;
using (MemoryStream compressedMemoryStream = new MemoryStream())
{
DeflateStream compressStream = new DeflateStream(compressedMemoryStream, CompressionMode.Compress, true);
compressStream.Write(data, 0, data.Length);
compressStream.Close();
retVal = new byte[compressedMemoryStream.Length];
compressedMemoryStream.Position = 0L;
compressedMemoryStream.Read(retVal, 0, retVal.Length);
compressedMemoryStream.Close();
compressStream.Close();
}
return retVal;
}
private static byte[] Decompress(byte[] data)
{
byte[] retVal;
using (MemoryStream compressedMemoryStream = new MemoryStream())
{
compressedMemoryStream.Write(data, 0, data.Length);
compressedMemoryStream.Position = 0L;
MemoryStream decompressedMemoryStream = new MemoryStream();
DeflateStream decompressStream = new DeflateStream(compressedMemoryStream, CompressionMode.Decompress);
decompressStream.CopyTo(decompressedMemoryStream);
retVal = new byte[decompressedMemoryStream.Length];
decompressedMemoryStream.Position = 0L;
decompressedMemoryStream.Read(retVal, 0, retVal.Length);
compressedMemoryStream.Close();
decompressedMemoryStream.Close();
decompressStream.Close();
}
return retVal;
}
答案 2 :(得分:2)
你应该有类似的东西:
public void CompressData(Stream uncompressedSourceStream, Stream compressedDestinationStream)
{
using (DeflateStream compressionStream = new DeflateStream(compressedDestinationStream, CompressionMode.Compress))
{
uncompressedSourceStream.CopyTo(compressionStream);
}
}
public void DecompressData(Stream compressedSourceStream, Stream uncompressedDestinationStream)
{
using (DeflateStream decompressionStream = new DeflateStream(uncompressedDestinationStream, CompressionMode.Decompress))
{
compressedSourceStream.CopyTo(decompressionStream);
}
}
using (FileStream sourceStream = File.OpenRead(@"C:\MyDir\MyFile.txt))
using (FileStream destinationStream = File.OpenWrite(@"C:\MyDir\MyCompressedFile.txt.cp"))
{
CompressData(sourceStream, destinationStream)
}
另外,请注意,您可能必须更改应用程序的.config文件中的WCF设置,以允许传输非常大的内容。
答案 3 :(得分:1)
您可以将DeflateStream包装在您自己的流中。每次要从压缩流中读取时,都必须将字节输入deflatestream,直到它写入缓冲区。然后,您可以从该缓冲区返回字节。
public class CompressingStream : Stream
{
private readonly DeflateStream _deflateStream;
private readonly MemoryStream _buffer;
private Stream _inputStream;
private readonly byte[] _fileBuffer = new byte[64 * 1024];
public CompressingStream(Stream inputStream)
{
_inputStream = inputStream;
_buffer = new MemoryStream();
_deflateStream = new DeflateStream(_buffer, CompressionMode.Compress, true);
}
public override int Read(byte[] buffer, int offset, int count)
{
while (true)
{
var read = _buffer.Read(buffer, offset, count);
if (read > 0) return read;
if (_inputStream == null) return 0;
_buffer.Position = 0;
read = _inputStream.Read(_fileBuffer, 0, _fileBuffer.Length);
if (read == 0)
{
_inputStream.Close();
_inputStream = null;
_deflateStream.Close();
}
else
{
_deflateStream.Write(_fileBuffer, 0, read);
}
_buffer.SetLength(_buffer.Position);
_buffer.Position = 0;
}
}
public override bool CanRead
{
get { return true; }
}
#region Remaining overrides...
}
每当wcf从流中读取时,压缩流将写入压缩DeflateStream,直到它从输出缓冲区(_buffer)读取为止。 这很难看,但它确实有效。
答案 4 :(得分:0)
我试图创建一个Stream,只要调用Read
:
DeflateStream
MemoryStream
的内容复制到阅读buffer
参数。当然,由于两个流的大小不相似,因此会更加困难。
最后我解除了这个选项,因为我发现没有办法预测生成的压缩文件的大小而没有在开始时完全压缩它。
然而,读取文件能够预测文件大小,因此可能有另一种DeflateStream
实现。
希望它有助于其他失落的灵魂......
答案 5 :(得分:0)
Blob的Azure API有一个替代UploadStream(流)。您可以使用OpenWrite()获取流。因此,现在您可以控制推送字节,因此可以在将内容流式传输到服务时进行压缩
using (var uploadStream = blob.OpenWrite())
using (var deflateStream = new DeflateStream(uploadStream, CompressionMode.Compress))
{
stream.CopyTo(deflateStream);
}
我没有检查WCF API,但如果你不能这样做,我会感到惊讶。