Как обнаружить ошибки CRC в файле при распаковке из zip - PullRequest
0 голосов
/ 20 сентября 2018

Я работаю в компании, которая имеет облачное базовое приложение, которое позволяет пользователям переносить файлы данных с ПК на мобильное устройство и обратно, позволяя пользователям обновлять и редактировать свои файлы в полевых условиях.

Случайно я столкнусь с проблемой, при которой во время передачи файла через веб-структуры структура zip будет повреждена, и случайный файл в zip-файле будет иметь ошибки crc.

Как правило, это будет изображение, но не всегда.Это вызывает проблемы с нашим программным обеспечением и препятствует загрузке файлов.Я написал инструмент, который сканирует zip-файл, ищет и исправляет ошибки в xml-файлах в zip-файле;однако функция System.IO.Compression.ZipFile.ExtractToDirectory не выдает ошибки, а извлекает файл и записывает его.

Вызов System.IO.Compression.ZipFile.CreateFromDirectory, который я делаю позже, затем архивирует этот файл, снова без ошибок, что приводит к тому, что zip-файл все еще имеет ошибку crc и все еще не открывается в нашем программном обеспечении.

Итак, вот мое connumdry, Как я могу проверить файлы, которые я извлекаю из zip-файла на наличие ошибок crc, и не помещать их в новый zip-файл, как только я закончу с другой моей работой?

У меня естьпопробовал несколько вещей и, если не считать загрузку каждого типа файла в какой-либо читатель (существует около дюжины типов файлов, которые могут быть в zip), я ничего не получил.

PS Я очень новичок вC # и у меня нет формального обучения кодированию, поэтому я могу задать несколько глупых вопросов, извините.: D

Пример можно найти здесь

ОК. Я попробовал то, что было предложено, и вот что я получил

Используя следующий код:

//https://johnlnelson.com/tag/zip-archive-c/ using ZipArchive
string zipFile = FileName;
string extractPath = @"C:\Temp\XAP\" + xapName;
ZipArchive zipArchive = ZipFile.OpenRead(zipFile);

if (zipArchive.Entries != null && zipArchive.Entries.Count > 0)
{
foreach (ZipArchiveEntry entry in zipArchive.Entries)
{
entry.ExtractToFile(System.IO.Path.Combine(extractPath, entry.FullName));
}
}

и генерируется следующая ошибка

ERROR:
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Temp\XAP\CRC in bmp\assignmentmap.bmp'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at System.IO.Compression.ZipFile

Код не может извлечь ни один из файлов в zip-файле, а не только поврежденный.

1 Ответ

0 голосов
/ 22 сентября 2018

Похоже, что проблема в сборке в ZipArchive из .NET Framework 4.5.Поврежденные файлы никак не сигнализируются.И, похоже, в SharpZipLib есть еще одна проблема.Ниже приведен полный пример кода, включая обнаружение повреждения для .NET Framework:

using System;
using System.IO;
using System.IO.Compression;

using ICSharpCode.SharpZipLib.Zip;

using DotNetZipFile = System.IO.Compression.ZipFile;

namespace Stackoverflow_unzip_test
{
  internal static class Program
  {
    private static void Main()
    {
      Extract45Framework("CRCerror.zip", ".\\Unpack_1");
      Console.WriteLine();
      Console.WriteLine();
      ExtractSharpZipLib("CRCerror.zip", ".\\Unpack_2");
    }

    private static void Extract45Framework(string zipFile, string extractPath)
    {
      ZipArchive zipArchive = DotNetZipFile.OpenRead(zipFile);

      if (zipArchive.Entries != null && zipArchive.Entries.Count > 0)
      {
        Console.WriteLine("Extracting...");
        foreach (ZipArchiveEntry entry in zipArchive.Entries)
        {
          try
          {
            if (string.IsNullOrEmpty(entry.Name))
            {
              // skip directory
              continue;
            }

            string file = Path.Combine(extractPath, entry.FullName);
            string path = Path.GetDirectoryName(file);
            if (!Directory.Exists(path))
            {
              Directory.CreateDirectory(path);
            }

            Console.WriteLine(" - '" + entry.FullName + "'...");
            if (File.Exists(file))
            {
              //Console.WriteLine("   - delete previous version...");
              File.Delete(file);
            }

            entry.ExtractToFile(file);
            long length = (new FileInfo(file)).Length;
            if (entry.Length != length)
            {
              Console.WriteLine($"   - Failed to extract! Extracted only {length} out of {entry.Length} bytes");
            }
          }
          catch (Exception ex)
          {
            Console.WriteLine("   - Failed to extract: " + ex.Message);
          }
        }
      }
    }

    private static void ExtractSharpZipLib(string zipFileName, string extractPath)
    {
      using (var file = File.OpenRead(zipFileName))
      using (ZipInputStream zip = new ZipInputStream(file))
      {
        ZipEntry entry;
        try
        {
          while ((entry = zip.GetNextEntry()) != null)
          {
            SaveFile(zip, entry, extractPath);
          }
        }
        catch (Exception ex)
        {
          Console.WriteLine("   - Failed to parse zip: " + ex.Message);
        }
      }
    }

    private static void SaveFile(ZipInputStream zip, ZipEntry entry, string extractPath)
    {
      if (entry.IsDirectory)
      {
        return;
      }

      try
      {
        string file = Path.Combine(extractPath, entry.Name);
        string path = Path.GetDirectoryName(file);
        if (!Directory.Exists(path))
        {
          Directory.CreateDirectory(path);
        }

        Console.WriteLine(" - '" + entry.Name + "'...");
        if (File.Exists(file))
        {
          //Console.WriteLine("   - delete previous version...");
          File.Delete(file);
        }

        byte[] data = new byte[1024];
        long length = 0;
        using (var fs = File.OpenWrite(file))
        {
          int readLength;
          while ((readLength = zip.Read(data, 0, data.Length)) != 0)
          {
            fs.Write(data, 0, readLength);
            length += readLength;
          }
        }

        if (entry.Size != length)
        {
          Console.WriteLine($"   - Failed to extract! Extracted only {length} out of {entry.Size} bytes");
        }
      }
      catch (Exception ex)
      {
        Console.WriteLine("   - Failed to extract: " + ex.Message);
      }
    }
  }
}

Вывод приложения:

Extracting...
 - 'tadd1.tx'...
 - 'assignmentmap.bmp'...
   - Failed to extract! Extracted only 34216 out of 34830 bytes
 - 'sketch.dsk'...


 - 'tadd1.tx'...
 - 'assignmentmap.bmp'...
   - Failed to extract: Index was outside the bounds of the array.
   - Failed to parse zip: Specified argument was out of the range of valid values.
Parameter name: count
...