2015-08-22 44 views
0

我一直在努力解決這個問題一段時間,但與編碼工作是如此痛苦,我必須得到一些幫助你的聰明頭腦。恢復與編碼不佳的文件名

在我對烏克蘭的一次旅行中,一個朋友複製到我的筆中驅動我一些烏克蘭的命名文件。然而,正如你所期望的,在複製到我的電腦的過程中,文件名變成了無法讀取的垃圾,比如這個:

Ôàíòîì 

嗯,我有充分的理由相信,原來的文件名使用CP1251編碼(我知道這是因爲我手動檢查編碼表並設法正確地翻譯樂隊的名稱)。顯然發生的是,在複製過程中,保留了CP1251代碼,現在操作系統只是將它們解釋爲Unicode代碼。

我試圖「解釋」在Python代碼與下面的腳本:

print u"Ôàíòîì".decode('cp1251') 

這感覺不對,雖然。其結果是完整的垃圾,以及:

Г」àíòîì 

如果我這樣做:

print repr(u"Ôàíòîì".decode('cp1251')) 

我獲得:

u'\u0413\u201d\u0413\xa0\u0413\xad\u0413\u0406\u0413\xae\u0413\xac' 

我發現,如果我能得到以Unicode的所有代碼點只是將它們抵消了0x350,我會把它們放在烏克蘭西里爾文的正確位置。但我不知道該怎麼做,可能有一個比這更概念正確的答案。

任何幫助將不勝感激!

編輯:這是正確的翻譯

Ôàíòîì應該翻譯成Фантом的例子。

Ô 0x00D4 -> Ф 0x0424 
à 0x00E0 -> а 0x0430 
í 0x00ED -> н 0x043D 
ò 0x00F2 -> т 0x0442 
î 0x00EE -> о 0x043E 
ì 0x00EC -> м 0x043C 

如前所述,正確和錯誤的代碼點之間有一個0x0350偏移量。

(ok,則該文件是音樂文件...我猜你懷疑......)

其他一些測試串(其翻譯我不知道): AACêîíò>即FL Äâîº Êàï_òîøêà Ïîäèâèñü

+0

可能的重複http://stackoverflow.com/questions/7555335/how-to-convert-a-string-from-cp1251-to-utf8 – saulspatz

+0

這不是CP1251;它看起來像是一個多字節[Mojibake](https://en.wikipedia.org/wiki/Mojibake);你有UTF-8或類似的,它被解碼錯誤。你可以看看['ftfy'庫](http://ftfy.readthedocs.org/en/latest/)是否可以做任何事情。它不能用於你給的樣品。 –

+0

您能和我們分享預期的價值嗎?然後,我們可以嘗試倒退,看看Mojibake是如何創建的,並扭轉過程。並考慮到字節可能已被*丟棄*,因爲它們不映射到可打印字符。給我們'print repr(value)'輸出,而不是'print value'輸出,這樣我們就可以在這裏做任何有意義的事情。 –

回答

0

我發現,除了網絡lenames,我所有的文件都正確編碼的元數據。

我發現MP3文件的ID3元數據標準只支持LATIN1,UTF8和UTF16編碼。

我的文件被設置爲處理latin1上的MP3文件包含的所有數據CP1251。大概是在俄羅斯和西里爾書寫國家的所有音樂播放器都設置理解LATIN1應該被解釋爲CP1251,這是不適合我的情況。

我用Python和誘變劑用於校正的元數據。當讀取的MP3元數據,誘變劑假設數據被編碼爲Latin1的表示亂碼字符作爲一個結果。我所要做的就是讓那些亂碼,他們再次和解碼編碼到LATIN1爲CP1251,獲得統一。然後,我改寫了MP3的元數據,然後誘變理解的是unicode的應保存爲UTF-8。與所有元數據是正確的。

要糾正我用下面的Python腳本文件元數據:

from mutagen.easyid3 import EasyID3 

def decode_song_metadata(filename): 
    id3 = EasyID3(filename) 
    for key in id3.valid_keys: 
     val = id3.get(key) 
     if val: 
      print key 
      decoded = val[0].encode('latin1').decode('cp1251') 
      print decoded 
      id3[key] = decoded 
    id3.save() 

def correct_metadata(): 
    paths = [u'/Users/felipe/Downloads/Songs']  

    for path in paths: 
     print 'path: ' + decode_filename(path) 
     for dirpath, dirnames, filenames in os.walk(path): 
      for filename in filenames: 
       try: 
        decode_song_metadata(os.path.join(dirpath, filename)) 
       except: 
        print filename 


if __name__ == '__main__': 
    correct_metadata() 

這糾正了MP3的元數據,但修正的文件名需要不同的技巧,因爲他們有一個differend編碼的問題。我覺得發生了什麼是原來的文件名是在CP1251,但是當他們從我的FAT32格式的U盤到我的Mac複製,MacOS的解釋文件名作爲latin1的。這種發源於文件名與怪異的重音字符,這是在「範式風化」,其中每個重音被保存爲比主字母不同Unicode字符編碼爲UTF-16。此外MACOS添加一個BOM標誌物污染的文件名。所以爲了糾正這一點,我不得不這樣做相反的操作:

  • 得到的文件名。這將返回一個Unicode字符串,其在範式風化拉丁重音符號。
  • 我們不得不再次轉換爲組成範式。
  • 那麼我們在編碼UTF-16。
  • 我們刪除了BOM。
  • 我們解釋進行解碼的CP1251。

爲了將文件名進行解碼然後我用下面的腳本:

def decode_filename(filename): 
    # MacOS filenames are stored in Unicode in "Normal Form Decomposed" 
    # form, where the accents are saved separated from the main 
    # character. Because the original characters weren't proper 
    # accentuated letters, in order to recover them we have to decompose 
    # the filenames. 
    # http://stackoverflow.com/a/16467505/212292 
    norm_filename = unicodedata.normalize('NFC', filename) 
    utf16 = norm_filename.encode('utf16') 
    bom = codecs.BOM_UTF16 

    if utf16.startswith(bom): 
     # We have to remove the BOM bytes 
     utf16 = utf16[len(bom):] 

    cp1251 = utf16.decode('cp1251') 
    return cp1251 

這應該與通過運行os.walk()方法返回的unicode的使用。

雖然上面的腳本工作,我最終沒有使用它來糾正文件名。我在啓用「Auto organizer」功能的情況下使用iTunes。這很棒,因爲每次我會在iTunes上播放歌曲時,它都會獲得mp3元數據(我已經使用上面的第一個腳本進行了更正),並將mp3文件重命名爲包含歌曲名稱,甚至文件夾。我發現這比糾正文件名更好,因爲這也可以正確地重命名文件夾並放置對歌曲有意義的文件名。

0

您可以添加此0x350像偏移:

的Python 2:

>>> s = u'Ôàíòîì' 
>>> decoded = u''.join([unichr(ord(c)+0x350) for c in s]) 
>>> print decoded 
Фантом 
+0

哇這個作品!但我想用編碼/解碼的答案來解決這個問題... –

1
>>> u'Ôàíòîì'.encode('latin1').decode('cp1251') 
'Фантом' 
+0

我喜歡這個問題。它適用於'Фантом'字符串,但是當我轉到下一個字符串時,它不能轉換某些字符。例如,這個:'Áåêîíò>'fl'會返回一個錯誤,但是如果我刪除了字符「>」和「fl」,它會翻譯爲:'Безконтол'(看起來是正確的,減去一些刪除的字符)。 –

1
>>> a = u'Ôàíòîì'.encode('8859').decode('cp1251') 
>>> print a 
Фантом  

如果你看看你的樣品中的單個字符大多來自斯拉夫語,但你必須在別人那裏從希臘和科普特,拉丁文擴展B和u'fe52' 是從全停超越的後面。所以這有點亂。
編輯:

一個=u'Ôàíòîì'.encode( 'CP1252')解碼( 'CP1251') 打印一個


幻影 一個=u'ÄâîºÊàï_òîøêà'。 .encode( 'CP1252')。解碼( 'CP1251') 打印一個


兩個Kap_toshka 一個=u'Ïîäèâèñü'.encode( 'CP1252')。解碼( 'CP1251')
打印一個 看

一個=u'Áåçêîíò>îë'.encode( 'CP1252')。解碼( 'CP1251') 打印一個

而不破壞>醇

CP1252適用於給定的樣本,除了Áåç êîíò›îëfl在拉美小結紮FL U + FB02似乎是多餘的