ZipEntry::ReadHeader(): Bad signature (0xE0FFD8FF) at position 0x00000000

Jan 4, 2010 at 2:20 PM
Edited Jan 4, 2010 at 3:09 PM

Hello and happy new year =3

 

I tried to convert compressed ZIP files into uncompressed ones, using a memory stream to reduce HDD usage, but I got this error:

ZipEntry::ReadHeader(): Bad signature (0xE0FFD8FF) at position 0x00000000

Here is some code:


using
( MemoryStream stream = new MemoryStream() ) { using( ZipFile zipOrg = ZipFile.Read( filepath ) ) { foreach( ZipEntry entry in zipOrg ) entry.Extract( stream ); // using( Stream s = entry.OpenReader() ) s.CopyTo( stream ); } // File.Delete( filepath ); stream.Seek( 0, SeekOrigin.Begin ); using( ZipFile zipNew = ZipFile.Read( stream ) ) { zipNew.CompressionLevel = Ionic.Zlib.CompressionLevel.None; zipNew.Save( filepathDebug ); // filepath } }

 

0xE0FFD8FF is the proper signature for a JPEG file, so what could be wrong ?

 

Using "Ionic.Zip.Reduced.dll" v1.8.4.28.

Coordinator
Jan 4, 2010 at 8:00 PM
Edited Jan 5, 2010 at 4:16 PM

I think what you've done is extract the first entry of a zip file, into memory (a MemoryStream). 

At that point you've tried to READ that MemoryStream as if it is a zip file.  This error that you receive is telling you that no, the data contained in the MemoryStream is a JPG file. 

Does that sound possible? 

This would work, if the first entry in the zip file, were another zip file. But in your case, it is a JPG file.

I'm not sure what you're trying to do, by extracting a zipfile into a stream.  Maybe you could explain the goal and I'll be able to make better suggestions.  What are you planning to do with the MemoryStream, once you've got a zip entry extracted into it?

 

Jan 5, 2010 at 8:51 PM
Edited Jan 5, 2010 at 11:54 PM

My goal in 3 steps :p

1. "c:\blah.zip" --> compression ratio: 0.97
2. Calling a magic function that only uses one memory stream.
3. "c:\blah.zip" --> compression ratio: 1

But it seems I was wrong in both form and content.

Form because obviously I should use "new ZipFile()" + "ZipFile::AddEntry( name, stream )" instead of "ZipFile.Read( stream )" which is more for http/ftp use (sorry for your lost time on that first post).

Content because it doesnt seem possible to do it with only one stream. There's no way to tell the size of the entry being added, so DotNetZip read from the given position to the very end. So if the original ZIP contains 3 files of respectivly 40, 50 and 60 KB once uncompressed, the files size in the new ZIP would be either 150, 110, 60 or 150, 0, 0 (depending of the way to do it).

I suppose I will have to open 1 stream per file in the given ZIP ? It would give this kind of (not particularly elegant ._.) code :

List<Stream> streams = new List<Stream>();

using( ZipFile zipNew = new ZipFile() )
{
	zipNew.CompressionLevel = Ionic.Zlib.CompressionLevel.None;
	using( ZipFile zipOrg = ZipFile.Read( fileName ) )
	{
		foreach( ZipEntry entry in zipOrg )
		{
			MemoryStream stream = new MemoryStream( (int) entry.UncompressedSize );
		//	Stream stream = entry.OpenReader();
			entry.Extract( stream );
			stream.Position = 0;
			zipNew.AddEntry( entry.FileName, stream );
			streams.Add( stream );
		}
	}
	zipNew.Save( fileName );
}

foreach( Stream stream in streams )
	stream.Close();

Coordinator
Jan 6, 2010 at 12:05 AM
Edited Jan 6, 2010 at 2:30 AM

You want to convert a zipfile so that compression is used on none of the entries? 

Ideally you could just read in the file, set the CompressionMethod on each entry, then re-save:

using( ZipFile zipNew = ZipFile.Read( file ) )
{
    foreach (ZipEntry e in  zipNew) 
    {
        e.CompressionMethod = Ionic.Zip.CompressionMethod.None;
    }
    zipNew.Save( filePath ); 
}

It should be equivalent to read in the file, then set the CompressionLevel on each entry, then re-save.

using( ZipFile zipNew = ZipFile.Read( file ) )
{
    foreach (ZipEntry e in  zipNew) 
    {
        e.CompressionLevel = Ionic.Zlib.CompressionLevel.None;
    }
    zipNew.Save( filePath ); 
}

I always intended for this to work, but when I looked today, I hadn't implemented it.  ??? I've just implemented it now.  You will need v1.9.0.37  to get this.  I will post it after running a few tests.

If you are using v1.8, then you can do something like this:

using (var zip = ZipFile.Read(zipFile))
{
    ZipEntry[] list = new ZipEntry[zip.Entries.Count];
    zip.Entries.CopyTo(list, 0);
    foreach (ZipEntry e in list)
    {
        var e2 = zip.UpdateEntry(e.FileName, "", e.OpenReader());
        e2.CompressionMethod = 0;
    }
    zip.Save();
}

What any of these options do, is this:  as the updated zip is written, it reads the old entry from a stream connected to the old zip file, and writes that content into the updated zip, where it uses the updated CompressionMethod/Level.  In the v1.9 versions, it happens automatically and implicitly, inside the library.  In the v1.8 code, you have to explicitly open the stream and hand it back to DotNetZip. 

 

Jan 6, 2010 at 1:33 AM
I will look into v1.9, looks good, also I wanted to try the promising multi-thread/core addition =3~~ Thank you for your detailed answers and dedicated support =^.^=
Coordinator
Jan 7, 2010 at 7:03 AM

ok Ara,

v1.9.0.37 is up and available.  With this release of DotNetZip, you can now do this:

using( ZipFile zipNew = ZipFile.Read( file ) )
{
    foreach (ZipEntry e in  zipNew) 
    {
        e.CompressionLevel = Ionic.Zlib.CompressionLevel.None;
    }
    zipNew.Save( filePath ); 
}

 

 

Jan 7, 2010 at 10:23 AM

Neat and working like a charm, thank you =3