Python zipfile module – zipfile.write () Datei mit türkischen Zeichen im Dateinamen

Auf meinem System gibt es viele Word-Dokumente und ich möchte sie mit dem Python-Modul zipfile .

Ich habe diese Lösung für mein Problem gefunden, aber auf meinem System gibt es Dateien, die deutsche Umlaute und türkische Charaktere in ihrem Dateinamen enthalten.

Ich habe die Methode von der Lösung so angepasst, damit sie deutsche Umlaute in den Dateinamen verarbeiten kann:

 def zipdir(path, ziph): for root, dirs, files in os.walk(path): for file in files: current_file = os.path.join(root, file) print "Adding to archive -> file: "+str(current_file) try: #ziph.write(current_file.decode("cp1250")) #German umlauts ok, Turkish chars not ok ziph.write(current_file.encode("utf-8")) #both not ok #ziph.write(current_file.decode("utf-8")) #both not ok except Exception,ex: print "exception ---> "+str(ex) print repr(current_file) raise 

Leider blieben meine Versuche, Logik für türkische Charaktere einzuschließen, erfolglos und verließen das Problem, dass jedes Mal, wenn ein Dateiname ein türkisches Zeichen enthält , der Code eine Ausnahme ausdruckt, zum Beispiel wie folgt:

 exception ---> [Error 123] Die Syntax f³r den Dateinamen, Verzeichnisnamen oder die Datentrõgerbezeichnung ist falsch: u'X:\\my\\path\\SomeTurk?shChar?shere.doc' 

Ich habe versucht, mehrere String-Codierung-Decodierung Zeug, aber keiner davon war erfolgreich.

Kann mir da jemand weiterhelfen?


Ich habe den oben genannten Code bearbeitet, um die im Kommentar erwähnten Änderungen einzuschließen.

Folgende Fehler werden nun angezeigt:

 ... Adding to archive -> file: X:\\my\path\blabla I blabla.doc Adding to archive -> file: X:\my\path\bla bla³bla³bla³bla.doc exception ---> 'ascii' codec can't decode byte 0xfc in position 24: ordinal not in range(128) 'X:\\my\\path\\bla B\xfcbla\xfcbla\xfcbla.doc' Traceback (most recent call last): File "Backup.py", line 48, in <module> zipdir('X:\\my\\path', zipf) File "Backup.py", line 12, in zipdir ziph.write(current_file.encode("utf-8")) UnicodeDecodeError: 'ascii' codec can't decode byte 0xfc in position 24: ordinal not in range(128) 

Das ³ ist eigentlich deutsch.


BEARBEITEN

Nachdem ich die vorgeschlagenen Dinge in den Kommentaren versucht habe, konnte ich keine Lösung ausarbeiten.

Deshalb wechselte ich zur Groovy Programming Language und verwendete seine Zip-Capabilities.

Da dies eine Meinungsbasierte Diskussion ist, habe ich beschlossen, für den Abschluss des Threads zu stimmen.

One Solution collect form web for “Python zipfile module – zipfile.write () Datei mit türkischen Zeichen im Dateinamen”

Wenn du die ZIP-Datei nicht später mit einem Archivierer inspizieren musst, kannst du sie immer auf base64 verschlüsseln und sie dann bei der Extraktion mit Python wiederherstellen.

Für jeden Archivierer werden diese Dateinamen wie Kauderwelsch aussehen, aber die Kodierung wird beibehalten.

Wie auch immer, um die 0-128 ASCII Bereich String (oder Bytes Objekt in Py3) zu bekommen, müssen Sie encodieren (), nicht decode ().

Encode () serialisiert den Unicode () String in ASCII Bereich.

 >>> u"\u0161blah".encode("utf-8") '\xc5\xa1blah' 

Decode () kehrt von diesem zu unicode () zurück:

 >>> "\xc5\xa1blah".decode("utf-8") u'\u0161blah' 

Gleiches gilt für jede andere Codepage.

Sorry für die Betonung, dass, aber die Menschen manchmal über die Kodierung und Dekodierung Zeug verwirrt.

Wenn Sie Dateien benötigen, aber Sie arent besorgt viel über das Erhalten von umlautes und andere Symbole, können Sie verwenden:

 u"üsdlakui".encode("utf-8", "replace") 

oder:

 u"üsdlakui".encode("utf-8", "ignore") 

Dies ersetzt unbekannte Zeichen mit möglichen oder völlig ignorieren alle Decodierung / Codierung Fehler.

Das wird die Dinge beheben, wenn der angehobene Fehler so etwas ist wie UnicodeDecodeError: Kann Zeichen nicht dekodieren …

Aber das Problem ist mit Dateinamen, die nur aus nicht-lateinischen Zeichen bestehen.

Jetzt etwas, das eigentlich funktionieren könnte:

Gut,

 'Sömethüng'.encode("utf-8") 

Ist verpflichtet, "ASCII-Encode-Fehler" zu erheben, da es keine Unicode-Zeichen gibt, die in der Zeichenfolge definiert sind, während nicht-lateinische Zeichen, die andere verwendet werden sollen, um Unicode / UTF-8 Zeichen zu beschreiben, verwendet werden, aber als ASCII-Datei selbst definiert ist nicht UTF- 8 codiert

während:

 # -*- coding: UTF-8 -*- u'Sömethüng'.encode("utf-8") 

oder

 # -*- coding: UTF-8 -*- unicode('Sömethüng').encode("utf-8") 

Mit Codierung definiert oben auf Datei und gespeichert als UTF-8 codiert sollte funktionieren.

Ja, du hast Strings von OS (Dateiname), aber das ist ein Problem vom Anfang der Geschichte.

Auch wenn die Codierung richtig verläuft, ist die ZIP-Sache noch zu lösen.

Nach Spezifikation sollte ZIP Dateinamen mit CP437 speichern, aber das ist selten so.

Die meisten Archiver verwenden die Standard-OS-Codierung (MBCS in Python).

Und die meisten Archiver unterstützen UTF-8 nicht. Also, was ich hier vorschlage, sollte funktionieren, aber nicht auf allen Archiven.

Um dem ZIP-Archiv zu sagen, dass das Archiv UTF-8 Dateinamen verwendet, sollte das elfte Bit von flag_bits auf True gesetzt werden. Wie ich schon sagte, einige von ihnen überprüfen das nicht. Das ist die letzte Sache in ZIP spec. (Nun, vor einigen Jahren wirklich)

Ich schreibe hier nicht den ganzen Code, nur der Teil musste das Ding verstehen.

 # -*- coding: utf-8 -*- # Cannot hurt to have default encoding set to UTF-8 all the time. :D import os, time, zipfile zip = zipfile.ZipFile(...) # Careful here, origname is the full path to the file you will store into ZIP # filename is the filename under which the file will be stored in the ZIP # It'll probably be better if filename is not a full path, but relative, not to introduce problems when extracting. You decide. filename = origname = os.path.join(root, filename) # Filenames from OS can be already UTF-8, but they can be a local codepage. # I will use MBCS here to decode from it, so that we can encode to UTF-8 later. # I recommend getting codepage from OS (from kernel32.dll on Windows) manually instead of using MBCS, but for now: if isinstance(filename, str): filename = filename.decode("mbcs") # Else, assume it is already a decoded unicode string. # Prepare the filename for archive: filename = os.path.normpath(os.path.splitdrive(filename)[1]) while filename[0] in (os.sep, os.altsep): filename = filename[1:] filename = filename.replace(os.sep, "/") filename = filename.encode("utf-8") # Get what we need zinfo = zipfile.ZipInfo(filename, time.localtime(os.getmtime(origname))[0:6]) # Here you should set zinfo.external_attr to store Unix permission bits and set the zinfo.compression_type # Both are optional and not a subject to your problem. But just as notice. zinfo.flag_bits |= 0x800 # Set 11th bit to 1, announce the UTF-8 filenames. f = open(origname, "rb") zip.writestr(zinfo, f.read()) f.close() 

Ich habe es nicht getestet, nur einen Code geschrieben, aber das ist eine Idee, auch wenn irgendwo in einem Bug kroch.

Wenn das nicht klappt, weiß ich nicht was wird.

  • Setzen Sie Berechtigungen für eine komprimierte Datei in python
  • Python zipfile-Modul scheint nicht zu komprimieren meine Dateien
  • Python - Extrahieren von Dateien aus einer großen (6GB +) Zip-Datei
  • Hinzufügen von Ordnern zu einer Zip-Datei mit Python
  • Python: Öffnen Sie die Datei aus dem Zip, ohne sie vorübergehend zu extrahieren
  • Wie kann ich nur die Ordner im Zip-Archiv in Python auflisten?
  • Wie entpacke ich eine Datei mit Python 2.4?
  • Suche () eine Datei innerhalb einer Zip-Datei in Python, ohne sie in den Speicher zu übergeben
  • Zipfile-Python-Modul Bytesize Unterschied
  • Python - wie man Unicode-Dateinamen in CP437 konvertiert?
  • CSV sollte Strings zurückgeben, nicht Bytes Fehler
  • Python ist die beste Programmiersprache der Welt.