I need to extract data from zip file that contains extra data.
When I opening it with 7-zip, it works fine, but there is warning in properties - "There are some data after the end of payload data"
But when I trying to unzip it with DotNetZip it gives me an error
using (var zip = ZipFile.Read("test.ef4"))
{
foreach (var zipEntry in zip)
{
Console.WriteLine(zipEntry.FileName);
var MemoryStream = new MemoryStream();
zipEntry.OpenReader().CopyTo(MemoryStream);
File.WriteAllBytes(zipEntry.FileName, MemoryStream.ToArray());
}
}
Exception:
Unhandled Exception: Ionic.Zip.ZipException: Cannot read that as a ZipFile
---> Ionic.Zip.BadReadException: Bad signature (0x0C000001) at position 0x00000060
How can I ignore this exception and unzip from file like 7-zip doing?
To reproduce it you can create archive with windows cmd.exe
Create archive.zip and extradata.txt with some random data. Then do this command -
copy /b archive.zip+extradata.txt
I found solution that worked for me:
All zip files have header like \x50\x4b\x01\x02 or \x50\x4b\x03\x04 in my case. (first \x50\x4b always the same. second half can be different)
So I wrote a code that founds offset of my ZIP file inside bytes. Footer of file is not important for any ziplib in C#
class Program
{
static void Main(string[] args)
{
var content = File.ReadAllBytes("qv.zip");
content = content.Skip(FirstPattern(content)).ToArray();
using (var zip = ZipFile.Read(new MemoryStream(content), new ReadOptions() {}))
{
foreach (var zipEntry in zip)
{
Console.WriteLine(zipEntry.FileName);
var MemoryStream = new MemoryStream();
zipEntry.OpenReader().CopyTo(MemoryStream);
File.WriteAllBytes(zipEntry.FileName, MemoryStream.ToArray());
}
}
}
private static int FirstPattern(byte[] bytes)
{
var header = StringToByteArray("504b0304"); // In my case all broken zip-files had 0304 ending
for (int i = 0; i < bytes.Length - header.Length; i++)
{
var j = 0;
while(j < header.Length && bytes[i + j] == header[j])
{
j++;
}
if(j == header.Length
return i;
}
return -1;
}
public static byte[] StringToByteArray(string hex)
{
int numberChars = hex.Length;
byte[] bytes = new byte[numberChars / 2];
for (int i = 0; i < numberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
}
User contributions licensed under CC BY-SA 3.0