- 論壇徽章:
- 3
|
本帖最后由 mci2004 于 2012-10-28 02:02 編輯
@starwing83 序哥,今天晚上又仔細看了下代碼,發(fā)現(xiàn)代碼中似乎不可能出現(xiàn)我昨天說的情況----在手機看到的亂碼就是latin1編碼。
1,
首先,可以確定你說的是對的,在vim上打個一個mp3文件看到的亂碼確實是latin1,為此我特地去查了ISO-8859-1,也就說明了一個文件在vim上如果它不認識直接就當作latin1來轉了。而且latin1是單字節(jié)的。
2,
關于locale的問題,我也查看了代碼,locale信息的確定實際上通過jdk里面的Local類來確定的。這個Locale的確定又和android的系統(tǒng)屬性有關。還記得我們昨天看到的那個函數(shù)嗎?- // if the locale encoding matches, then assume we have a native encoding.
- if (encoding & mLocaleEncoding)
復制代碼 事實上這個函數(shù)是做一個double check后面一個mLocalEncoding是通過android系統(tǒng)在java層獲得的。前面一個encoding是通過findPossibleEncoding()---查巨表的函數(shù)獲得的。如果這兩個相等就非常確定可以是四種字符集中的某一個了,就可以交給下面的conertValues()了。
3,
回到最開始的問題,我為什么可以確定latin1編碼不可能出現(xiàn)呢?因為,我看到了下面的代碼
還記得endFile()這個函數(shù)吧?在沒有比配成功字符集后,會直接交給上層去處理,也就是下面的邏輯- // if the locale encoding matches, then assume we have a native encoding.
- if (encoding & mLocaleEncoding)
- convertValues(mLocaleEncoding);
- // finally, push all name/value pairs to the client
- for (int i = 0; i < mNames->size(); i++) {
- status_t status = handleStringTag(mNames->getEntry(i), mValues->getEntry(i));
- if (status) {
- break;
- }
復制代碼 convertValues沒有機會執(zhí)行,那么直接handleSringTag,這個時候那個傳過來的字符(亂碼那個)被當作一個字符串傳進了handleString里(沒做任何處理)。
//序哥下面是最后一個函數(shù)handleStringTag,主要關注value參數(shù),它是亂碼- virtual status_t handleStringTag(const char* name, const char* value)
- {
- ALOGV("handleStringTag: name(%s) and value(%s)", name, value);
- jstring nameStr, valueStr;
- if ((nameStr = mEnv->NewStringUTF(name)) == NULL) {
- mEnv->ExceptionClear();
- return NO_MEMORY;
- }
- // Check if the value is valid UTF-8 string and replace
- // any un-printable characters with '?' when it's not.
- char *cleaned = NULL;
- //判斷是不是utf-8原理很簡單,看單個字節(jié)是否在0x80-->0xBF之間,序哥這里有什么要補充的嗎?
- if (utf8_length(value) == -1){
- cleaned = strdup(value);
- char *chp = cleaned;
- char ch;
- while ((ch = *chp)) {
- if (ch & 0x80) {
- //看這里,如果不是utf-8且字符在0x80之后,就認為是unprintable,然后設置成‘?’。
- *chp = '?';
- }
- chp++;
- }
- value = cleaned;
- }
- valueStr = mEnv->NewStringUTF(value);
- free(cleaned);
- if (valueStr == NULL) {
- mEnv->DeleteLocalRef(nameStr);
- mEnv->ExceptionClear();
- return NO_MEMORY;
- }
- mEnv->CallVoidMethod(
- mClient, mHandleStringTagMethodID, nameStr, valueStr);
- mEnv->DeleteLocalRef(nameStr);
- mEnv->DeleteLocalRef(valueStr);
- return checkAndClearExceptionFromCallback(mEnv, "handleStringTag");
- }
復制代碼 所以我覺得應該會被顯示成'?'才對啊。難道序哥,這個字符傳到java層會被轉換城latin1嗎?不可能吧,java的文檔我查了,沒有這個說法?
但是我肯定我在手機上看到的那個亂碼是latin1. |
|