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