歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Android Media 播放mp3時ID3 tag 顯示亂碼的探究分析。

Android Media 播放mp3時ID3 tag 顯示亂碼的探究分析。

日期:2017/2/28 16:22:29   编辑:Linux教程

我們從Windows的中文操作系統下,下載下來mp3,Tag正常顯示,推進Android機後,卻出現亂碼,這是為什麼呢?

之所以在中文系統中沒有特別的問題,是因為通常電腦生成的MP3簡體中文ID3標簽是ID3V2.3版本,編碼是ANSI,GB2312/GBK從雙字節上兼容ANSI標准。而在UTF-8/Unicode為標准的系統中如Linux(Ubuntu),Android中就容易出現這種問題。

解決辦法先明確幾個知識點:

首先明確一點,文件不存在什麼編碼(歸根結底文件都是二進制文件,用ue打開可以看到都是一個個的16進制數),只有文件中的字符才可以說編碼。

unicode和ansi都是字符代碼的一種表示形式。

使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。

  不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬於兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。

常見編碼介紹

ansi編碼

最初的計算機是又8個晶體管,通過晶體管的開合與排列可以表示數種狀態,所以一個字節就定義為8bit,而一個bit只能有0,1開關的表示,2的8次方是256,所以最初的計算機只能表示256種狀態。

人們定義了前32個為狀態字符比如翻頁,換行,發出(嘟)的聲音等,後來人們為了用計算機存儲文字,又把空格,英文字母,數字等加進了進來,總共使用了127個,這時候大家把這個存儲方案叫做ANSI的ASCII編碼[American Standard Code for Information Interchange,美國信息互換標准代碼](http://www.dreamdu.com/xhtml/ascii/),這個表存儲英文已經沒有 問題了,但是127個裡並不包含其它歐洲國際的文字,人們又繼續擴展ASCII表的內容,加入了一些字符,與一些畫表格的符號,直接擴展到255個。

ASCII和Ansi編碼

字符內碼(charcter code)指的是用來代表字符的內碼.讀者在輸入和存儲文檔時都要使用內碼,內碼分為

單字節內碼 -- Single-Byte character sets (SBCS),可以支持256個字符編碼.

雙字節內碼 -- Double-Byte character sets)(DBCS),可以支持65000個字符編碼.

前者即為ASCII編碼,後者對應ANSI.

至於簡體中文編碼GB2312,實際上它是ANSI的一個代碼頁936

GB2312與GBK

國人發現只使用ASCII表根本無法表示漢字!怎麼辦?沒有什麼能難道我們!於是我們發明了GB2312編碼,此編碼完全忽略了ASCII表中 127位後面的內容,127位前面的內容保留,如果兩個字節同時大於127(7F)就認為這兩個字節表示一個漢字,同時像標點、字母也都重新使用兩個字節 定義了一遍,這就是我們經常說的 全角,這種方案可以表示6000種文字。

但是中國的文字太復雜6000個字也不夠用,人們開始擴展GB2312,規定只要一個字節大於127,這個字節和後面的字節組合起來就代表一個漢字,這種編碼成為GBK,於是又增加了20000多個漢字!

這樣很多國家都開始定義自己的編碼了,日本,韓國等。甚至連中國的台灣省都定義了一種編碼 BIG5。所以在當時一個程序要想適應多國語言簡直要把人郁悶死。

如果搞過Windows編程的人應該知道,win裡面有多字節字符集MBCS(multi-byte character set)的說法,而且MBCS包含兩種字符類型,單字節字符SBCS(single-byte characters set)和雙字節字符(double-byte characters set)DBCS。我們的GBK與GB2312都是DBCS。所以我們在編程時經常遇到一個中文字符等於兩個英文字符的事情。BIG5與日本韓國的編碼也 都屬於DBCS。

這下清楚了吧,根本沒什麼ansi文件或gb2312文件,文件打開時會根據操作系統的編碼方式(就是安裝在操作系統中的編碼解析方式)來嘗試打開文件,如果安裝了中文編碼,就把ansi文件當作中文打開,如果日文編碼,就當作日文打開。

UNICODE與UTF-8

ISO最後提出了UNICODE(Universal Multiple-Octet Coded Character Set,簡稱 UCS)編碼來解決所有的問題。

UNICODE編碼方式規定使用兩個字節(16位)表示表示一個字符,算算2的16次方是多少?原來ANSI規定的都擴充為2字節,並且把所有已知的語言都編碼進UNICODE。UNICODE可以表示65536個字符。

這下多國語言程序開始高興了,使用UNICODE全部搞定!於是微軟重現編輯Windows內核,完全使用UNICODE編碼,搞過win編程的人應該都知道,以A或W結尾的函數,還有靈巧的_T宏吧?

雖然UNICODE有很多優點,但是缺點也不少,我先總結我知道的兩點:

1,狂占空間,以前一個字節可以表示,現在卻要用兩個字節了,網絡上有80%屬於英文字符,這下網絡幾乎要擴大一倍!

所以又有人研究出來了UTF-8(Unicode Translation Format - 8)編碼,UNICODE轉換格式,對於常用字符使用單字節,漢字等使用雙字節。8代表每次在網絡上傳輸8位,如果是UTF-16就是每次傳輸16位。搞 過網絡編程的朋友應該知道,字節序(就是字節的排放順序)分為兩種,主機字節序與網絡字節序,就是大頭(俗稱)在前,小頭在前的問題,在網絡上面傳輸的流 的字節序很可能是不一致的,於是需要使用一種方法通知接收端,傳輸流的字節序。有人發明了一種簡單的方法,在每個流的開始加上FFEF或EFFF,分別主 機與網絡字節序,我們可以使用記事本保存一個UNICODE文件,再使用ue打開看看(HEX方式打開)。所以有時候網頁傳到網上,在網頁最開始的地方會 出現一個字符,這個有時候很令人費解。

用記事本新建立兩個文件存為UNICODE與UNICODE big endian模式,輸入夢之都,保存再用ue打開。

UNICODE

FF FE A6 68 4B 4E FD 90

UNICODE big endian

FE FF 68 A6 4E 4B 90 FD (觀察,沒兩個字節和上面的對比)

2,UNICODE與GBK等兩字節編碼完全不兼容,無法找到一種簡單的方式轉換(只能使用查找表的方式)

這點我們可以使用記事本新建立兩個文件一個ansi的文件,另一個utf8的文件,分別寫入夢之都 ,保存。使用ue的hex模式打開我們會看到。

UNICODE

FF FE A6 68 4B 4E FD 90

ansi

C3 CE D6 AE B6 BC

很著名的問題,如果用記事本輸入“聯通”保存,再打開,發現“聯通”兩個字沒了!為什麼沒有了,大家可以自己分析一下。有人說這就是聯通競爭不過移動的原因。

清楚了這些,那麼我想,必須先判斷出是什麼國家文字的歌曲,再用什麼方式去解ANSI標准碼 ,最後轉換成utf-8顯示。概括一句話:讓utf-8正確解析雙字節的ANSI。

Copyright © Linux教程網 All Rights Reserved