2016-01-20 152 views
2

我試圖將用C編寫的程序移植到使用NDK和JNI的Android中,並且我陷入了一個令人發瘋的荒謬問題。(Android NDK)包含非ASCII字符的字符串被切斷

要長話短說,如果我這樣做...

char str[1024]; 
sprintf(str, "Hellö, this is söme stränge letters."); 

... 的strlen(STR)返回35,符合市場預期。對?

但是,如果我包括符,並且做到這一點...

char str[1024]; 
sprintf(str, "Hellö again. Here's a number: %d", 1); 

... 的strlen(STR)返回4

你看到發生了什麼?看起來NDK不能(或不會)接受字符串中的非ASCII字符,如果我嘗試格式化它們。

任何時候我在格式字符串中包含大於127的ASCII字符時,它都會被截斷。就像它是以NULL結尾的。

這是一個錯誤?這是預期的行爲?

最終,我的問題是:我該怎麼做才能解決這個問題?

非常感謝提前。

+0

你看過str的編碼嗎?它很可能是以非ASCII友好的方式編碼的,例如UTF-8。 – bruceg

+0

@bruceg不,對不起,我沒有。我怎麼做? – user5716859

+0

_「我該怎麼做?」_執行'str'內容的hexdump(即對於值爲0的字節,打印爲「00」;對於值255,打印爲「FF」等)。 – Michael

回答

2

Android 5.0的「預覽」版本有一些問題在最終版本中得到修復。有關更多信息,請參閱this bug report

如果您得到.o文件的十六進制轉儲(例如在Linux上爲xxd)並搜索字符串的一個片段,您可以看到它在可執行文件中的編碼方式。如果它是有效的UTF-8 - 當我使用桌面gcc進行編譯時,我得到'ö'c3 b6 - 那麼它應該可以工作。如果使用其他編碼,則Android libc可能會將其拒絕爲無效。

如果二進制文件中的字符串看起來不是UTF-8,請檢查您的makefile文件以獲得像-fexec-charset=這樣的東西。

+0

我用HxD來看它,如果我正確地閱讀它,「ö」只是一個字節,它是十六進制的F6。我的makefiles中也沒有任何'-fexec-charset ='。我正在用Windows構建ndk-build。我的構建目標是android-22(5.1.1),我的手機是5.1.1。我無法讓sprintf()接受這些字符... – user5716859

+0

這就解釋了拒絕。您需要將字符的UTF-8編碼表達式轉換爲字符串。 (作爲一個實驗,試着明確地加上它,例如'「Hell \ xc3 \ xb6 again」。)獲得源文件的十六進制轉儲,以查看你的編輯器是否正在編寫UTF-8或CP-1252-gcc可能不會明白你的意圖。如果你不能配置你的編輯器來編寫UTF-8,你可能需要指定'-finput-charset ='gcc來匹配它實際使用的任何東西。 FWIW,在錯誤報告中我注意到一些人發現更容易丟棄替換'sprintf()'的例子。 – fadden