System.IO.Compression.ZipFile.NET 4.5 выход zip не подходит для Linux/Mac/Java

При использовании класса .NET System.IO.Compression.ZipFile.CreateFromDirectory результат zip файла плохо извлекается в системе с помощью разделителя каталогов прямой косой черты.

Причина: Почтовый индекс содержит обратную косую черту внутри имен

Ответы

Ответ 1

Для преодоления этой проблемы существует обходное решение:

    class MyEncoder : UTF8Encoding
    {
        public MyEncoder()
        {

        }
        public override byte[] GetBytes(string s)
        {
            s = s.Replace("\\", "/");
            return base.GetBytes(s);
       }
    }
    System.IO.Compression.ZipFile.CreateFromDirectory("C:/ABC", "C:/tmp/ABC.zip", CompressionLevel.Fastest, false, new MyEncoder());

Ответ 2

Microsoft обратилась к этому в .NET 4.6.1:

Начиная с приложений, нацеленных на .NET Framework 4.6.1, разделитель путей, используемый в свойстве ZipArchiveEntry.FullName, изменился с обратной косой черты ( "\" ), используемой в предыдущих версиях .NET Framework, на косую черту ( "/" ). Объекты System.IO.Compression.ZipArchiveEntry создаются путем вызова одной из перегрузок метода ZipFile.CreateFromDirectory.

Примечание:

Кроме того, приложения, ориентированные на предыдущие версии .NET Framework, но работающие на .NET Framework 4.6.1 и более поздних версиях, могут использовать это поведение, добавив параметр конфигурации в раздел файла конфигурации приложения.

Ответ 3

Правильная работа для этой проблемы выглядит следующим образом

class MyEncoder : UTF8Encoding
{
    public MyEncoder() : base(true)
    {

    }
    public override byte[] GetBytes(string s)
    {
        s = s.Replace("\\", "/");
        return base.GetBytes(s);
   }
}

ПРИМЕЧАНИЕ. Это немного отличается от предыдущего ответа.

Основное различие заключается в : base(true)

Это важно, или класс .NET ZipArchive НЕ распознает кодировщик как кодировщик UTF-8 и НЕ отметит правильный бит общего назначения, и, таким образом, извлечение полученного zip файла с помощью любой другой почтовой программы займет запись zip имя находится в кодировке, отличной от юникода, которая может привести к искажению имени файла.

Причина связана с внутренним вызовом в .NET, чтобы проверить, не является ли пользовательский кодер .equals(Encoding.UTF8), который не является истинным, если только true не передается для encoderShouldEmitUTF8Identifier, такого как Encoding.UTF8