استخراج الملفات مع أحرف غير صالحة في اسم الملف مع بيثون
سؤال
وأنا استخدم وحدة zipfile الثعبان لانتزاع أرشيف الرمز البريدي (دعونا نلقي هذا الملف على HTTP :. //img.dafont.com/dl/ و = akvaleir على سبيل المثال)
f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
print fileinfo.filename
f.extract(fileinfo, '.')
وانتاجها:
Akval�ir_Normal_v2007.ttf
Akval�ir, La police - The Font - Fr - En.pdf
وكلا الملفين هي unaccessable بعد استخراج لأن هناك شخصيات المشفرة غير صالحة في أسماء الملفات الخاصة بهم. المشكلة هي ليس لديها وحدة zipfile خيار لتحديد أسماء الانتاج.
ولكن، "بفك akvaleir.zip" يهرب اسم الملف أيضا:
root@host:~# unzip akvaleir.zip
Archive: akvaleir.zip
inflating: AkvalВir_Normal_v2007.ttf
inflating: AkvalВir, La police - The Font - Fr - En.pdf
وحاولت التقاط الإخراج من "بفك -l akvaleir.zip" في برنامج بيثون بلدي وهذه أسماء هما:
Akval\xd0\x92ir_Normal_v2007.ttf
Akval\xd0\x92ir, La police - The Font - Fr - En.pdf
وكيف يمكنني الحصول على اسم الملف الصحيح مثل ما بفك قيادة يفعل دون التقاط الإخراج من "بفك -l akvaleir.zip"؟
المحلول
وبدلا من طريقة extract
، استخدم open
طريقة وحفظ pseudofile مما أدى إلى القرص تحت أي اسم شئت، على سبيل المثال مع <لأ href = "http://docs.python.org/library/shutil.html؟highlight=shutil#shutil.copyfileobj "يختلط =" noreferrer "> shutil.copyfileobj
.
نصائح أخرى
واستغرق الأمر بعض الوقت، ولكن أعتقد أنني وجدت الجواب.
وتوليت كلمة كان من المفترض أن يكون Akvaléir. لقد وجدت وصفا الصفحة عن ذلك، باللغة الفرنسية. عندما كنت مقتطف الشفرة كان لي سلسلة مثل
>>> fileinfo.filename
'Akval\x82ir, La police - The Font - Fr - En.pdf'
>>>
وهذا لم ينجح في UTF8، اللاتينية-1، CP-1251 أو ترميزات-CP 1252. ثم وجدت أن CP863 كان ترميز الكندي ممكن، لذلك ربما كان هذا من كندا الفرنسية.
>>> print unicode(fileinfo.filename, "cp863").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>>
ولكن، وبعد ذلك قراءة البريدي تنسيق ملف مواصفات التي تقول
<اقتباس فقرة>وتنسيق ZIP له تاريخيا معتمد فقط على أجهزة الكمبيوتر IBM الأصلي مجموعة أحرف الترميز، وعادة يشار إلى رمز IBM الصفحة 437.
...
إذا تم تعيين أغراض العامة بت 11، اسم الملف والتعليق يجب أن يعتمد يونيكود الموحدة، النسخة 4.1.0 أو أكبر باستخدام ترميز الأحرف شكل يحددها تخزين UTF-8 المواصفات.
اقتباس فقرة>واختبار أنه من يعطيني الجواب نفسه صفحة الرموز الكندية
>>> print unicode(fileinfo.filename, "cp437").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>>
وأنا لم يكن لديك ملف مضغوط يونيكود المشفرة وأنا لست بصدد إنشاء واحدة لمعرفة، ولذا فإنني سوف مجرد افتراض أن جميع الملفات المضغوطة لديها ترميز cp437.
import shutil
import zipfile
f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
filename = unicode(fileinfo.filename, "cp437")
outputfile = open(filename, "wb")
shutil.copyfileobj(f.open(fileinfo.filename), outputfile)
في بلدي ماك الذي يعطي
109936 Nov 27 01:46 Akvale??ir_Normal_v2007.ttf
25244 Nov 27 01:46 Akvale??ir, La police - The Font - Fr - En.pdf
والذي يكمل التبويب ل
ls Akvale\314\201ir
ويظهر مع 'é "لطيفة في المتصفح ملفي.
وأنا واجهت مشكلة مشابهة أثناء تشغيل التطبيق الخاص بي باستخدام عامل الميناء. إضافة هذه الأسطر إلى Dockerfile، كل شيء ثابت بالنسبة لي:
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
وهكذا، وأنا أعتقد إذا كنت لا تستخدم عامل الميناء، ومحاولة إعطائها وجعل يتم إنشاؤها بشكل صحيح المؤكد غات وضعها.