ZLIB من C ++ إلى C # (كيفية تحويل البايت [] إلى الدفق والدفق إلى البايت [])
سؤال
مهمتي هي إلغاء ضغط الحزمة (المستلمة) باستخدام Zlib ثم استخدم Glgoritm لإجراء صورة من البيانات
والخبر السار هو أن لدي رمز في C ++، ولكن المهمة هي القيام بذلك في C #
C ++.
//Read the first values of the packet received
DWORD image[200 * 64] = {0}; //used for algoritm(width always = 200 and height always == 64)
int imgIndex = 0; //used for algoritm
unsigned char rawbytes_[131072] = {0}; //read below
unsigned char * rawbytes = rawbytes_; //destrination parameter for decompression(ptr)
compressed = r.Read<WORD>(); //the length of the compressed bytes(picture)
uncompressed = r.Read<WORD>(); //the length that should be after decompression
width = r.Read<WORD>(); //the width of the picture
height = r.Read<WORD>(); //the height of the picture
LPBYTE ptr = r.GetCurrentStream(); //the bytes(file that must be decompressed)
outLen = uncompressed; //copy the len into another variable
//Decompress
if(uncompress((Bytef*)rawbytes, &outLen, ptr, compressed) != Z_OK)
{
printf("Could not uncompress the image code.\n");
Disconnect();
return;
}
//Algoritm to make up the picture
// Loop through the data
for(int c = 0; c < (int)height; ++c)
{
for(int r = 0; r < (int)width; ++r)
{
imgIndex = (height - 1 - c) * width + r;
image[imgIndex] = 0xFF000000;
if(-((1 << (0xFF & (r & 0x80000007))) & rawbytes[((c * width + r) >> 3)]))
image[imgIndex] = 0xFFFFFFFF;
}
}
أحاول القيام بذلك مع zlib.net، ولكن جميع العروض لديها هذا الرمز لإلغاء ضغط (C #)
private void decompressFile(string inFile, string outFile)
{
System.IO.FileStream outFileStream = new System.IO.FileStream(outFile, System.IO.FileMode.Create);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outFileStream);
System.IO.FileStream inFileStream = new System.IO.FileStream(inFile, System.IO.FileMode.Open);
try
{
CopyStream(inFileStream, outZStream);
}
finally
{
outZStream.Close();
outFileStream.Close();
inFileStream.Close();
}
}
public static void CopyStream(System.IO.Stream input, System.IO.Stream output)
{
byte[] buffer = new byte[2000];
int len;
while ((len = input.Read(buffer, 0, 2000)) > 0)
{
output.Write(buffer, 0, len);
}
output.Flush();
}
مشكلتي: لا أريد حفظ الملف بعد إلغاء الضغط، لأنني لا بد لي من استخدام Algoritm الموضح في رمز C ++.
كيفية تحويل صفيف البايت [] إلى دفق متشابه إلى واحد في رمز C # ZLIB لإلغاء ضغط البيانات ثم كيفية تحويل الدفق مرة أخرى إلى صفيف بايت؟
أيضا، كيفية تغيير رمز Zlib.net لعدم حفظ الملفات؟
المحلول
ما عليك سوى استخدام مخصصات بدلا من FileStreams:
// Assuming inputData is a byte[]
MemoryStream input = new MemoryStream(inputData);
MemoryStream output = new MemoryStream();
ثم يمكنك استخدام output.ToArray()
بعد ذلك للحصول على صفيف بايت خارج.
لاحظ أنه من الأفضل بشكل عام الاستخدام using
البيانات بدلا من تجربة واحدة / كتلة أخيرا - كما خلاف ذلك إذا كانت الدعوة الأولى إلى Close
فشل، لن يتم الاستراحة. يمكنك أن تتبعهم مثل هذا:
using (MemoryStream output = new MemoryStream())
using (Stream outZStream = new zlib.ZOutputStream(output))
using (Stream input = new MemoryStream(bytes))
{
CopyStream(inFileStream, outZStream);
return output.ToArray();
}
نصائح أخرى
لقد ركضت فقط في هذه المشكلة نفسها.
للكمال ... (لأن هذا كذبني لعدة ساعات)
في حالة Zlib.net، يجب عليك أيضا الاتصال بالإنهاء ()، والتي تحدث عادة أثناء الإغلاق ()، قبل أن تتصل بإخراج الإرجاع.
وإلا فستحصل على صفيف بايت فارغ / غير مكتمل من دفق الذاكرة، لأن Zstream لم يكتب بالفعل جميع البيانات بعد:
public static void CompressData(byte[] inData, out byte[] outData)
{
using (MemoryStream outMemoryStream = new MemoryStream())
using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream, zlibConst.Z_DEFAULT_COMPRESSION))
using (Stream inMemoryStream = new MemoryStream(inData))
{
CopyStream(inMemoryStream, outZStream);
outZStream.finish();
outData = outMemoryStream.ToArray();
}
}
public static void DecompressData(byte[] inData, out byte[] outData)
{
using (MemoryStream outMemoryStream = new MemoryStream())
using (ZOutputStream outZStream = new ZOutputStream(outMemoryStream))
using (Stream inMemoryStream = new MemoryStream(inData))
{
CopyStream(inMemoryStream, outZStream);
outZStream.finish();
outData = outMemoryStream.ToArray();
}
}
في هذا المثال، أنا أيضا استخدام مساحة اسم ZLIB:
using zlib;
وجدت أصلا في هذا الموضوع:ZLIB decumpression
ليس لدي نقاط كافية للتصويت حتى الآن، لذلك ...
بفضل تيم Greaves for the Tip فيما يتعلق بالانتهاء قبل التوارد
و JON SKEET للحصول على طرف فيما يتعلق بالتعشيش البيانات باستخدام التدفقات (التي أحبها أفضل بكثير من المحاولة / أخيرا)