2016-01-20 75 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