The following is a simple compression method I wrote using DeflateStream
:
public static int Compress(
byte[] inputData,
int inputStartIndex,
int inputLength,
byte[] outputData,
int outputStartIndex,
int outputLength)
{
if (inputData == null)
throw new ArgumentNullException("inputData must be non-null");
MemoryStream memStream = new MemoryStream(outputData, outputStartIndex, outputLength);
using (DeflateStream dstream = new DeflateStream(memStream, CompressionLevel.Optimal))
{
dstream.Write(inputData, inputStartIndex, inputLength);
return (int)(memStream.Position - outputStartIndex);
}
}
What is special in this method is that I didn't use the parameter-less constructor of MemoryStream
. This is because it is a high-throughput server. Array outputData
is rented from ArrayPool
, to be used to hold the compressed bytes, so that after I make use of it I can return it to ArrayPool
.
The compression happened properly, and the compressed data is properly placed into outputData
, but memStream.Position
was zero, so I can't find out how many bytes have been written into the MemoryStream
.
Only part of outputData
is occupied by the compressed data. How do I find out the length of the compressed data?
CodePudding user response:
MemoryStream.Position
is 0 because data was not actually written there yet at the point you read Position
. Instead, tell DeflateStream
to leave underlying stream (MemoryStream
) open, then dispose DeflateStream
. At this point you can be sure it's done writing whatever it needs. Now you can read MemoryStream.Position
to check how many bytes were written:
public static int Compress(
byte[] inputData,
int inputStartIndex,
int inputLength,
byte[] outputData,
int outputStartIndex,
int outputLength)
{
if (inputData == null)
throw new ArgumentNullException("inputData must be non-null");
using (var memStream = new MemoryStream(outputData, outputStartIndex, outputLength)) {
// leave open
using (DeflateStream dstream = new DeflateStream(memStream, CompressionLevel.Optimal, leaveOpen: true)) {
dstream.Write(inputData, inputStartIndex, inputLength);
}
return (int) memStream.Position; // now it's not 0
}
}
You also don't need to substract outputStartIndex
, because Position
is already relative to that index you passed to constructor.