Es scheint, dass die Dateinamencodierung jeder in der Zip-Datei archivierten Datei das Vorhandensein oder Fehlen des UTF-8-Flags (in der aktuellen Version) angeben kann, aber die andere Codierung als UTF-8 kann nicht angegeben werden. ..
Bei der Komprimierung in Windows mit japanischem Gebietsschema (je nach Tool) wird der Dateiname in Shift_JIS (CP932) geschrieben. Die meisten modernen Linux und Mac sind UTF-8.
Wenn Sie eine auf einem anderen Betriebssystem komprimierte Zip-Datei dekomprimieren, kann sie problemlos dekomprimiert werden, wenn das UTF-8-Flag vorhanden ist. Wenn jedoch Shift_JIS (CP932) verwendet wird, wird der Dateiname verstümmelt. Es kann passieren.
Insbesondere Windows → Linux / Mac usw. In diesem Fall können Sie einen Archivierer wie "unar" verwenden oder den verstümmelten Dateinamen mit "convmv" korrigieren.
Abgesehen davon erkennt die ZipFile-Bibliothek von Python auch Dateinamen nicht richtig.
Die ZipFile-Bibliothek konvertiert Bytes als UTF-8 in Zeichenfolgen, wenn ein UTF-8-Flag vorhanden ist, andernfalls als CP437.
Wenn Sie versuchen, mit ZipFile.extractall ()
usw. zu erweitern, wird der japanische Dateiname daher mit verstümmelten Zeichen erweitert.
Die Problemumgehung besteht darin, "ZipInfo.filename" wieder in eine Byte-Zeichenfolge als CP437 umzuwandeln, dann wieder in eine Zeichenfolge mit der richtigen Codierung und "ZipFile.extract (ZipInfo)" zu nennen.
import zipfile
f = r'/file/to/path'
with zipfile.ZipFile(f) as z:
for info in z.infolist():
info.filename = info.filename.encode('cp437').decode('cp932')
z.extract(info)
Oben wird die ursprüngliche Codierung als CP932 verarbeitet, in der Realität ist dies jedoch nicht immer der Fall. Daher ist es besser, die Codierungsbeurteilung oder die Ausnahmeverarbeitung zu verwenden.
Es gibt kein Problem, wenn das Extrahieren mit ZipFile auf einem Mac ausgeführt wird. Wenn Sie jedoch versuchen, unter Windows zu extrahieren, tritt abhängig vom Dateinamen ein Fehler auf.
ZipInfo.filename
ersetzt os.sep
durch/
. Das heißt, unter Windows wird \
(\ x5c
) durch /
(\ x2f
) ersetzt.
CP437 ist eine 1-Byte-Zeichencodierung, und ASCII-Druckzeichen (\ x20
- \ x7f
) sind ASCII-kompatibel, sodass dieser Ersetzungsprozess ausgeführt wird (auch wenn er ursprünglich Teil von Mehrbyte-Zeichen ist). Ich werde am Ende. Sobald Sie zur Byte-Zeichenfolge zurückkehren, wird ein Muster wie "b" \ x90 \ x2f "angezeigt.
Shift_JIS (CP932) verwendet niemals das zweite Byte "\ x2f". Wenn Sie also versuchen, eine solche Byte-Zeichenfolge erneut in eine Zeichenfolge wie CP932 zu konvertieren, tritt ein Dekodierungsfehler auf. Ich werde.
Dieses Problem tritt auf, wenn das zweite Byte das Zeichen "\ x5c" ist.
damit. Es ist ein sogenannter "schlechter Charakter". (Obwohl der Grund für den Fehler anders war als dieser)
Nein. Ich habe die schlechten Charaktere von Shift_JIS (CP932) in den letzten 10 Jahren völlig vergessen. Mit einer sich ändernden Kugel wird shift_JIS (CP932) zu einer ungültigen Byte-Zeichenfolge, indem sie durch "\ x2f" ersetzt wird.
Die Dateinameninformationen (dekodiert als CP437) vor dem Ersetzungsprozess werden in "ZipInfo.orig_filename" gespeichert, mit dem das Problem gelöst werden kann.
import os
import zipfile
f = r'/file/to/path'
with zipfile.ZipFile(f) as z:
for info in z.infolist():
info.filename = info.orig_filename.encode('cp437').decode('cp932')
if os.sep != "/" and os.sep in info.filename:
info.filename = info.filename.replace(os.sep, "/")
z.extract(info)
Recommended Posts