using gzlib from c#

B

Bonj

I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work. The
call to compress doesn't return or throw an exception, it simply bombs the
program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) == 0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
B

Bonj

I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
 
B

Bonj

I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the same
thing aswell.
 
C

Carl Daniel [VC++ MVP]

Bonj said:
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the same
thing aswell.

I suspect it's the ref byte[] that's the problem. You need to pass a pinned
pointer to the array data. I believe in C# terms that means you need to use
and unsafe {} block around the call.

-cd
 
W

Willy Denoyette [MVP]

Using pointers in an unsafe context.

[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
unsafe static extern void compress(byte* dest, ref int destlen,
.................);

outputbytes = new byte[outputlen];
unsafe {
fixed (byte* bPtr = outputbytes )
{
if(compress(bPtr , ref outputlen,......);
...
}
}

Willy.

Bonj said:
I tried it with
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the same
thing aswell.


Bonj said:
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) == 0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
B

Bonj

Thanks, that seems to work.

Bonj said:
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the same
thing aswell.


Bonj said:
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) == 0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
S

Stefan Simek

You can avoid using unsafe code:

[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);
}
finally
{
hSource.Free();
hDest.Free();
}
}

But I would recommend using the SharpZipLib anyway.

HTH,
Stefan

Bonj said:
Thanks, that seems to work.

Bonj said:
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the
same thing aswell.


Bonj said:
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) ==
0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
G

Guest

You can avoid using unsafe code:

Why, is there anything bad about it?
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);

Oh right! that looks good, i'll try that.

Thanks!
But I would recommend using the SharpZipLib anyway.

Nah - I've tried it, and it's not lossless. It retrieved the first half of
the data correctly - but that's about it. The returned uncompressed data was
truncated , chopped in half. I'm not going to use something that's unreliable.
 
G

Guest

In addition, SharpZipLib is developed by "SharpDevelop" - I've tried the
"SharpDevelop" "IDE" before and found it appalling, so I don't actually trust
anything written by them.
It set up a load of bogus users with random strings as their names, and made
them owners of its directory structure, I had to fiddle around removing them
all after I'd uninstalled it. Cygwin did exactly the same thing (only to its
own directory structure though). (GNU people trying their hand at Microsoft
stuff? What's that all about anyway?)
And whoever's written "SharpZipLib" - however well they've tried to convert
it, it can only be a maximum of two years old - as that's how old C# is. The
unmanaged version looks like it's been around a lot longer than that, and
seems to have gone through numerous versions and bug fixes.


Stefan Simek said:
You can avoid using unsafe code:

[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);
}
finally
{
hSource.Free();
hDest.Free();
}
}

But I would recommend using the SharpZipLib anyway.

HTH,
Stefan

Bonj said:
Thanks, that seems to work.

Bonj said:
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the
same thing aswell.


"Bonj" <benjtaylor at hotpop d0t com> wrote in message
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) ==
0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
G

Guest

Don't trust it. See reply to Stefan.

Deepak said:
Bonj,

There is another Opensource Gzip library and this one is for .NET. I have
used it, and works well. You can download it from
http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx


Regards,

Deepak
[I Code, therefore I am]



Bonj said:
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to work. The
call to compress doesn't return or throw an exception, it simply bombs the
program. I'm probably calling it wrong, but have no idea why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source, uLong
sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen) == 0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
J

Jon Skeet [C# MVP]

Bonj said:
Nah - I've tried it, and it's not lossless. It retrieved the first
half of the data correctly - but that's about it. The returned
uncompressed data was truncated , chopped in half. I'm not going to
use something that's unreliable.

You still haven't shown us the code for that. I'd be willing to bet
that it was a mistake in your code rather than SharpZipLib. If you
think I'm wrong, please post a short but complete program which
demonstrates the problem.

There are lots of people using this library - do you think they'd all
be using it if it were losing their data?
 
G

Guest

You still haven't shown us the code for that.

No I haven't. It wasn't my code, it was some that was on
www.planetsourcecode.com.
I'd be willing to bet
that it was a mistake in your code rather than SharpZipLib.

At the end of the day, it wasn't my code. It was off planet sourcecode. But
it did look correct. All it seemed to be doing was firing the constructor of
stream-type objects. At the end of the day, I'm going to try the unmanaged
DLL, and if it decompresses accurately, then there's no reason why I would
invest more time and energy in getting a reworked one to work.
If you
think I'm wrong, please post a short but complete program which
demonstrates the problem.

Well I could do, but I don't know what I'd get out of it.
There are lots of people using this library - do you think they'd all
be using it if it were losing their data?

No - I'm not saying it doesn't work at all. It obviously just doesn't work
for me.
But at the end of the day, porting such a library to .NET seems pointless
when MS have taken the trouble to provide advanced features such as PInvoke,
GCHandle objects, unsafe/fixed, etc. for us to use, on tried and trusted
unmanaged code. And also, it might be just very few coincidental cases where
it fails - but still does so even with the correct code wrapping it, and I
just happened to have been unlucky in having fallen into one of those
coincidences.
But however good the open source "all in .NET" library is, I can quite
easily see how these coincidences are due to extremely subtle subtleties in
the original C/C++ code that have been ported wrongly. I'm not dissing the
programmer that did port this library - but like I say - .NET has only been
around for just over 2 years, and call me cynical - but it seems like too
much effort has been spent customizing it so that it can work in an 'elegant
OOP way' with streams, which I can't help but think is simply an excuse to
faff around with streams, just for the sake of faffing around with streams.
Me, I just want to pass a byte array in and get a smaller byte array back.
 
S

Stefan Simek

Almost nothing, I just try to avoid it when possible - I guess the primary
use for unsafe code is for performance reasons, and even then, only after
all other ways of optimization fail. And it requires you to set the 'Allow
unsafe code' flag. Sounds evil.

Guess it's a matter of personal preference.

Stefan

Bonj said:
You can avoid using unsafe code:

Why, is there anything bad about it?
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr
source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint
sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);

Oh right! that looks good, i'll try that.

Thanks!
But I would recommend using the SharpZipLib anyway.

Nah - I've tried it, and it's not lossless. It retrieved the first half of
the data correctly - but that's about it. The returned uncompressed data
was
truncated , chopped in half. I'm not going to use something that's
unreliable.
 
S

Stefan Simek

Well, your very funny kind of person.

First, you are going to write your own encryption, own compression and
whatever else, because you think you'll do better than people whose products
are widespread.

On the other hand, you won't use a library because it's only TWO YEARWS

Bonj said:
In addition, SharpZipLib is developed by "SharpDevelop" - I've tried the
"SharpDevelop" "IDE" before and found it appalling, so I don't actually
trust
anything written by them.
It set up a load of bogus users with random strings as their names, and
made
them owners of its directory structure, I had to fiddle around removing
them
all after I'd uninstalled it. Cygwin did exactly the same thing (only to
its
own directory structure though). (GNU people trying their hand at
Microsoft
stuff? What's that all about anyway?)
And whoever's written "SharpZipLib" - however well they've tried to
convert
it, it can only be a maximum of two years old - as that's how old C# is.
The
unmanaged version looks like it's been around a lot longer than that, and
seems to have gone through numerous versions and bug fixes.


Stefan Simek said:
You can avoid using unsafe code:

[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr
source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint
sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);
}
finally
{
hSource.Free();
hDest.Free();
}
}

But I would recommend using the SharpZipLib anyway.

HTH,
Stefan

Bonj said:
Thanks, that seems to work.

"Bonj" <benjtaylor at hotpop d0t com> wrote in message
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen, byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the
same thing aswell.


"Bonj" <benjtaylor at hotpop d0t com> wrote in message
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to
work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea
why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen,
byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen)
==
0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
S

Stefan Simek

My fingers got tied up... ;)

.... *two years* since people begun to use it?

Just for fun, I've used the SharpZipLib yesterday for the first time. I've
made several tests and it didn't fail me even once. It works perfectly for
anything I could try.

Stefan

Stefan Simek said:
Well, your very funny kind of person.

First, you are going to write your own encryption, own compression and
whatever else, because you think you'll do better than people whose
products are widespread.

On the other hand, you won't use a library because it's only TWO YEARWS

Bonj said:
In addition, SharpZipLib is developed by "SharpDevelop" - I've tried the
"SharpDevelop" "IDE" before and found it appalling, so I don't actually
trust
anything written by them.
It set up a load of bogus users with random strings as their names, and
made
them owners of its directory structure, I had to fiddle around removing
them
all after I'd uninstalled it. Cygwin did exactly the same thing (only to
its
own directory structure though). (GNU people trying their hand at
Microsoft
stuff? What's that all about anyway?)
And whoever's written "SharpZipLib" - however well they've tried to
convert
it, it can only be a maximum of two years old - as that's how old C# is.
The
unmanaged version looks like it's been around a lot longer than that, and
seems to have gone through numerous versions and bug fixes.


Stefan Simek said:
You can avoid using unsafe code:

[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern short compress(IntPtr dest, ref uint destLen, IntPtr
source,
uint sourceLen);

short compress(byte[] dest, ref uint destLen, byte[] source, uint
sourceLen)
{
// do some checking on null references...

GCHandle hDest = GCHandle.Alloc(dest, GCHandleType.pinned);
GCHandle hSource = GCHandle.Alloc(source, GCHandleType.pinned);

try
{
return compress(hDest.AddrOfPinnedObject(), ref destLen,
hSource.AddrOfPinnedObject(), sourceLen);
}
finally
{
hSource.Free();
hDest.Free();
}
}

But I would recommend using the SharpZipLib anyway.

HTH,
Stefan

"Bonj" <benjtaylor at hotpop d0t com> wrote in message
Thanks, that seems to work.

"Bonj" <benjtaylor at hotpop d0t com> wrote in message
I tried it with
[DllImport("zlib1.dll", CallingConvention=CallingConvention.Cdecl)]
static extern Int16 compress(ref byte[] dest, ref uint destlen,
byte[]
source, int sourcelen);
and it still does the same thing, bombs on the call to that method.

I also tried it with the return value as int (Int32) and that did the
same thing aswell.


"Bonj" <benjtaylor at hotpop d0t com> wrote in message
I downloaded the gzlib library from zlib in order to do compression.
(http://www.gzip.org/zlib)
The prototype of the compression function seems to be
int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong
sourceLen);
It is meant to be called by C, but I would rather use it from C#.

So I wrote the following C# program to test it, but it failed to
work.
The call to compress doesn't return or throw an exception, it simply
bombs the program. I'm probably calling it wrong, but have no idea
why.

This is the program:
using System;
using System.IO;
using System.Security;
using System.Runtime.InteropServices;

class class1
{
// int compress (Bytef *dest, uLongf *destLen, const Bytef *source,
uLong sourceLen);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("zlib1.dll")]
static extern Int16 compress(ref byte[] dest, ref uint destlen,
byte[]
source, int sourcelen);

static void Main(string[] args)
{
if(args.Length != 2)
{
Console.WriteLine("Usage: testgz <inputfile> <outputfile>");
return;
}
try
{
int filelen = (int)((new FileInfo(args[0])).Length);
uint outputlen = (uint)Math.Ceiling(1.001 * filelen) + 12;
using(FileStream fsr = new FileStream(args[0], FileMode.Open,
FileAccess.Read, FileShare.Read))
{
byte[] inputbytes = new byte[filelen],
outputbytes = new byte[outputlen];
fsr.Read(inputbytes, 0, filelen);
if(compress(ref outputbytes, ref outputlen, inputbytes, filelen)
==
0)
using(FileStream fsw = new FileStream(args[1], FileMode.Create,
FileAccess.Write, FileShare.Read))
{
fsw.Write(outputbytes, 0, (int)outputlen);
fsw.Close();
}
fsr.Close();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
 
C

Carl Daniel [VC++ MVP]

Bonj said:
Me, I just want to pass a byte array in and get a smaller
byte array back.

Just one comment not related to the managed/native disucssion: Worst-case
performance for most compression libraries will yield a "compressed" object
that's just slightly larger than the original. Make sure you're not
depending on the compressed data actually being smaller. The worst case
performance generally occurs with input data that is either A) very short or
B) already compressed or C) well encrypted.

-cd
 
J

Jon Skeet [C# MVP]

Bonj said:
No I haven't. It wasn't my code, it was some that was on
www.planetsourcecode.com.

Could you give us the exact URL?
At the end of the day, it wasn't my code. It was off planet sourcecode. But
it did look correct. All it seemed to be doing was firing the constructor of
stream-type objects. At the end of the day, I'm going to try the unmanaged
DLL, and if it decompresses accurately, then there's no reason why I would
invest more time and energy in getting a reworked one to work.

I suspect it will actually take *less* effort to get the managed code
working, given my experiences with interop...
Well I could do, but I don't know what I'd get out of it.

An entirely managed solution, which means you don't require as many
security permissions to use it, you don't need to worry about leaking
memory in unmanaged code, the threading implications are easier to
understand, you can step in with the debugger if necessary, etc.
No - I'm not saying it doesn't work at all. It obviously just doesn't work
for me.

And that's what suggests that it's the use of it which is wrong rather
than the library.
But at the end of the day, porting such a library to .NET seems pointless
when MS have taken the trouble to provide advanced features such as PInvoke,
GCHandle objects, unsafe/fixed, etc. for us to use, on tried and trusted
unmanaged code.

Why not apply the same logic to everything else though? Why bother
using FileStream when you can just p/invoke fopen somehow? Managed code
is simply easier to use.
And also, it might be just very few coincidental cases where
it fails - but still does so even with the correct code wrapping it, and I
just happened to have been unlucky in having fallen into one of those
coincidences.

Until I've seen the code, I'm slightly unwilling to believe that it
*is* the correct code. For instance, I've seen a *lot* of code which
assumes that a call to Stream.Read will read as many bytes as are asked
for, ignoring the return value. A bug like that could easily scupper
things.
But however good the open source "all in .NET" library is, I can quite
easily see how these coincidences are due to extremely subtle subtleties in
the original C/C++ code that have been ported wrongly.

Actually it's the Java code which has been ported to .NET here - and
that Java code has been in the Java base library since JDK 1.1 - in
other words, a fairly long time.
I'm not dissing the programmer that did port this library

Well, you're saying that his code is buggy...
- but like
I say - .NET has only been around for just over 2 years, and call me
cynical - but it seems like too much effort has been spent
customizing it so that it can work in an 'elegant OOP way' with
streams, which I can't help but think is simply an excuse to faff
around with streams, just for the sake of faffing around with
streams.

No, it's done because streams are the idiomatic way of working with
what are naturally streams of data. The fact that it *does* use streams
is what enabled me to allow a Compact Framework application I was
working on to accept compressed data with about 5 lines of code - I
just wrapped the Stream I was given back by HttpWebResponse in a
GzipInputStream. Very easy, and elegant.
Me, I just want to pass a byte array in and get a smaller
byte array back.

Enjoy your time with interop then. I know I wouldn't...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top