Поврежден zip при передаче потока памяти SharpZipLib в PclStorage
В PCL я использую SharpZipLib.Portable, чтобы заархивировать некоторый контент в MemoryStream, а затем записываю MemoryStream в файл Zip с помощью средства двоичной записи PCLStorage. Однако созданный zip-файл поврежден. При перечислении его содержимого я получаю сообщение:
Архив: zippedfile.zip
предупреждение [zippedfile.zip]: 20 дополнительных байтов в начале или внутри zip-файла
(пытаясь обработать в любом случае)
ошибка [zippedfile.zip]: начало центрального каталога не найдено;
Zip-файл поврежден.
(убедитесь, что вы перенесли или создали zip-файл в
соответствующий режим BINARY и что вы правильно скомпилировали UnZip)
Код ниже. Кто-нибудь может подсказать, где я иду не так? Я не представляю на мгновение, что-то не так с SharpZipLib или PCLStorage, однако есть странная аномалия:
[Редактировать: Некоторый новый свет на аномалию, описанную ниже: Каждое вхождение байта больше 7F транслируется в тройку байтов EF BF BD, что, по-видимому, является многобайтовым представлением UTF8 разновидности символа вопросительного знака. Таким образом, похоже, что PCLStorage рассматривает поток как UTF8. Тогда возникает вопрос, как убедить PCLStorage сделать двоичную передачу. ]
При передаче потока в PCLStorage я проверяю поток в точке останова (переменная 'verify') и вижу, что шестнадцатеричное содержимое правдоподобно похоже на формат ZIP, например, с правильным заголовком ZIP:
50 4B 03 04 14 00 00 00 08 00 45 89 52 48 DF 36... (122 байта)
Когда я затем смотрю на созданный zip-файл в шестнадцатеричном редакторе, я также вижу что-то похожее на формат ZIP, но в теле файла оно отличается!:
50 4B 03 04 14 00 00 00 08 00 45 EF BF BD 52 48... (142 байта)
В обоих случаях эквивалент ASCII имеет форму:
PK....... ABCD.txt.... PK..... ABCD.txt..... PK.....
Аналогичные результаты при использовании кода с fileHandler.WriteAsync вместо.CopyTo.
Другие люди используют двоичную передачу PCLStorage, поэтому я сомневаюсь, что проблема в этом. Что мне не хватает? Любые предложения приветствуются.
Это в Xamarin Forms PCL.
// using ICSharpCode.SharpZipLib.Zip; // SharpZipLib.Portable
// using PCLStorage;
string content = "ABCD\r\n"; // Desired content of zipped file
byte[] contentBytes = Encoding.UTF8.GetBytes ( content );
using ( MemoryStream contentStream = new MemoryStream () )
{
await contentStream.WriteAsync ( contentBytes, 0, contentBytes.Length );
contentStream.Position = 0;
using ( MemoryStream zipStream = new MemoryStream () )
{
using ( ZipOutputStream s = new ZipOutputStream ( zipStream ) )
{
s.UseZip64 = UseZip64.Off;
s.SetLevel (6); // Compression level
//Add the text file
ZipEntry csvEntry = new ZipEntry ( "ABCD.txt" );
s.PutNextEntry ( csvEntry );
await contentStream.CopyToAsync (s);
s.CloseEntry ();
s.IsStreamOwner = false; // Do not close zipStream when finishing
await s.FlushAsync (); // Write to zipStream
s.Finish ();
}
// Save file to local file system
IFolder rootfolder = FileSystem.Current.LocalStorage;
IFolder exportfolder = await rootfolder.CreateFolderAsync ( "Exports", CreationCollisionOption.OpenIfExists );
IFolder subfolder = await exportfolder.CreateFolderAsync ( "Zips", CreationCollisionOption.OpenIfExists );
IFile file = await subfolder.CreateFileAsync ( "ZippedFile.zip", CreationCollisionOption.ReplaceExisting );
using (Stream fileHandler = await file.OpenAsync ( FileAccess.ReadAndWrite ) )
{
zipStream.Position = 0;
await zipStream.CopyToAsync ( fileHandler );
// As a sanity check, view the contents of fileHandler
using ( MemoryStream memStream = new MemoryStream () )
{
fileHandler.Position = 0;
fileHandler.CopyTo ( memStream );
byte[] verify = memStream.ToArray ();
} // Put breakpoint here to view contents of verify
}
}
1 ответ
Простите, ребята. Виноват! Написанный код работает правильно и создает правильный файл ZIP в файловой системе. Мой тестовый код был проблемой.
-- Билл.