2014-12-04 6 views
16

Bei der Verwendung von .NET System.IO.Compression.ZipFile.CreateFromDirectory Klasse ist das Ergebnis zip auf System mit Forward schlecht extrahiert -slash Verzeichnis Trennzeichen.System.IO.Compression.ZipFile .NET 4.5 Ausgabe zip in nicht geeignet für Linux/Mac/Java

Grund: Der Reißverschluss enthält Backslash in dem Namen

+1

Die erstellten ZIP-Dateien sind auch von 'fremden' Lesern wie LibreOffice (auch unter Windows) unbrauchbar, da die Backslashes die Spezifikation verletzen. Dies wurde in .NET Foundation behoben - siehe https://github.com/dotnet/corefx/commit/7b9331e89a795c72709aef38898929e74c343dfb. –

Antwort

14

Um dieses Problem zu überwinden, eine Abhilfe besteht:

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()); 
+0

Sie sollten nur Schrägstriche in Ihrem Code weiterleiten. Es funktioniert auch unter Windows, wissen Sie, p – leppie

+0

@leppie Ist das nicht, was er gerade mit dieser Problemumgehung getan hat? –

+0

@ LasseV.Karlsen: Aber das wird auch den eigentlichen Inhalt beeinflussen, sagen wir in Textdateien. Nein? – leppie

8

Die richtige Arbeit um für dieses Problem als

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

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

HINWEIS : Dies ist etwas anders als eine vorherige Antwort.

Der wesentliche Unterschied ist in dem : base(true)

Dies ist wichtig, oder .NET ZipArchive Klasse wird nicht den Encoder als UTF-8-Encoder erkennt und wird nicht den richtigen Mehrzweck Bit markieren und damit das Extrahieren des resultierenden Zip-Datei mit jedem anderen Zip-Programm wird davon ausgehen, dass der Name des Zip-Eintrags in einer Nicht-Unicode-Codierung ist, die zu einem mangelnden Dateinamen führen kann.

Der Grund ist, auf einen internen Anruf in .NET wegen zu prüfen, ob die benutzerdefinierte Encoder .equals(Encoding.UTF8) ist das nicht wahr ist, es sei denn, true für die encoderShouldEmitUTF8Identifier wie Encoding.UTF8 geben wird

+0

ich habe diese Lösung zu meinem Code hinzugefügt, aber jetzt habe ich eine Nachricht von Linux Base Server bekommen, da der Stammordner nicht in der Zip gefunden werden kann. Ich habe es manuell entpackt, aber dort ist der Stammordner vorhanden. Irgendeine Hilfe ? Mein Code ist 'System.IO.Compression.ZipFile.CreateFromDirectory (" C:/ABC "," C:/tmp/ABC.zip ", CompressionLevel.Fastest, True, neuer MyEncoder()); ' –

9

Microsoft hat addressed this in .NET 4.6.1:

Beginnend mit Apps, die auf .NET Framework 4.6.1 abzielen, wurde der in der ZipArchiveEntry.FullName-Eigenschaft verwendete Pfadtrenner von dem in früheren Versionen von .NET Framework verwendeten umgekehrten Schrägstrich ("\") in einen Schrägstrich geändert. "/"). System.IO.Compression.ZipArchiveEntry-Objekte werden durch Aufrufen einer der Überladungen der ZipFile.CreateFromDirectory-Methode erstellt.

Hinweis:

Darüber hinaus Anwendungen, die früheren Versionen des .NET Framework abzielen, sondern auf dem .NET Framework 4.6.1 und späteren Versionen ausgeführt werden, können durch das Hinzufügen einer zu diesem Verhalten entscheiden in Konfigurationseinstellung auf den Abschnitt der Anwendungskonfigurationsdatei.

+1

Wie kann ich das mit Powershell tun? Ich habe PS 5, aber es sieht so aus, als ob es immer noch die pleite zip-Version verwendet? – red888