استخراج الملفات مع أحرف غير صالحة في اسم الملف مع بيثون

StackOverflow https://stackoverflow.com/questions/1807063

سؤال

وأنا استخدم وحدة 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

وهكذا، وأنا أعتقد إذا كنت لا تستخدم عامل الميناء، ومحاولة إعطائها وجعل يتم إنشاؤها بشكل صحيح المؤكد غات وضعها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top