JNI:将Java字符串转换为代码页1252 我使用JNI来实现java程序和C++函数之间的接口。C++函数处理多字节字符串(CP 1252)。我用这个C++代码把java字符串转换成ch**:< /p> char *arg=(char*) jEnv->GetStringUTFChars(jArg2,0);
这很好,除非我有一些高阶字符。例如,如果我的输入是: Àlan(联合技术部队:c2 6c 61 6e 20 4a 6f 6e 65 7e) 我可以看到结果arg是: c3 82 6c 61 6e 但是,我希望看到: c0 6c 61 6e 看到GetStringUTFChars()应该返回UTF字符串,我尝试使用GetStringChars()获取Unicode字符串,并通过WideChartMultiByte()进行转换: (您可以假设我已经正确地分配了str并设置了szStr)。在这种情况下,我在结果str中看到了这一点: c3 82 6c 61 6e 我尝试过WideChartMultiByte的第一个参数的其他CP_uu值,没有一个产生有用的结果(它们要么返回上述值,要么用“?”代替“À”) 我希望我能得到这样的结果: c0 6c 61 6eJNI:将Java字符串转换为代码页1252 我使用JNI来实现java程序和C++函数之间的接口。C++函数处理多字节字符串(CP 1252)。我用这个C++代码把java字符串转换成ch**:< /p> char *arg=(char*) jEnv->GetStringUTFChars(jArg2,0);,java,c++,unicode,java-native-interface,Java,C++,Unicode,Java Native Interface,这很好,除非我有一些高阶字符。例如,如果我的输入是: Àlan(联合技术部队:c2 6c 61 6e 20 4a 6f 6e 65 7e) 我可以看到结果arg是: c3 82 6c 61 6e 但是,我希望看到: c0 6c 61 6e 看到GetStringUTFChars()应该返回UTF字符串,我尝试使用GetStringChars()获取Unicode字符串,并通过WideChartMultiByte()进行转换: (您可以假设我已经正确地分配了str并设置了szStr)。在这种情况下
但到目前为止,我还没有运气。代码页1252,Windows ANSI Western,是ISO Latin 1的超集。ISO Latin 1是Unicode的子集。因此,如果您可以在没有欧元符号和其他一些添加的Microsoft字符的情况下生活,只需丢弃任何高于255的Unicode代码点,您就拥有一个有效的cp 1252编码字符串 要正确使用
WideCharToMultiByte
(更通用的转换,例如支持欧元符号),请阅读文档,并注意标记值等
或者,正如我们过去在Usenet上所说的,有些人希望其他人为他们阅读文档,告诉他们什么是重要的,什么不是重要的,请使用RTFM。Java使用了一个经过修改的UTF-8版本。以下是Java文档中的一段引文:
修改后的UTF-8对于Java平台来说并不新鲜,但它确实是一种东西
应用程序开发人员在转换时需要更加注意
可能包含UTF-8之间的补充字符的文本。
要记住的主要一点是,一些J2SE接口使用
类似于UTF-8但与之不兼容的编码
编码在过去有时被称为“Java修改的UTF-8”
或者(错误地)只是“UTF-8”
正在更新,统一称之为“修改的UTF-8”
改良UTF-8与标准UTF-8茎的不相容性
首先,修改后的UTF-8表示字符
U+0000作为双字节序列0xC0 0x80,而标准UTF-8使用
单字节值0x0。秒,修改的UTF-8表示
通过分别编码两个代理代码来补充字符
UTF-16表示的单位。每个代理代码单位
由三个字节表示,总共六个字节。标准
另一方面,UTF-8使用单个四字节序列作为
完整的性格
Java虚拟机和接口使用修改的UTF-8
附加到它(如Java本机接口、各种工具
接口(或Java类文件),在Java.io.DataInput和
实现或使用它们的DataOutput接口和类,以及
Java本机接口提供的例程
转换为修改后的UTF-8。另一方面,标准UTF-8,
String类、java.io.InputStreamReader和
OutputStreamWriter类、java.nio.charset工具和许多
在它们上面分层的API
由于修改后的UTF-8与标准UTF-8不兼容,因此
关键是不要在需要另一个的地方使用一个。改进的UTF-8可以
只能与上述Java接口一起使用
案例,特别是针对可能来自或可能来自的数据流
由不基于Java平台的软件解释,
必须使用标准UTF-8
当使用标准UTF-8时,无法使用与修改的UTF-8之间的转换
是必需的
字节序列c2 6c 61 6e 20 4a 6f 6e 65 7e
在标准UTF-8下无效。在cp1252中,相同的字节序列将是字符串lan Jone~
(注意而不是À
)
在标准UTF-8下,字符串Àlan Jone
将是字节序列c3 80 6c 61 6e 20 4a 6f 6e 65 7e
(注意c3 80 6c
而不是c2 6c
)
所有Java字符串本机都是UTF-16,因此不需要将字符串作为UTF-8检索。使用GetStringChars()
获取原始UTF-16编码字符,并按原样将其传递到WideCharToMultiByte()
指定1252
作为代码页(注意,在您的示例中,您对UTF-16输入缓冲区和cp1252输出缓冲区都使用了str
——不要混淆变量!),例如:
感谢您的全面响应,str是一个剪切/粘贴错误,在我的测试中它实际上是正确的。我没有意识到WideChartMultiByte的第一个参数可能是实际的代码页,我认为只允许文档中列出的定义。下次,请更仔细地阅读文档:-):“此参数可以设置为操作系统中已安装或可用的任何代码页的值…您的应用程序还可以指定下表中显示的值之一。。。“实际上,为了解决这个问题,我在两个函数上都做了RTFM,我忽略了参数1实际上可能是代码页而不仅仅是CP_*定义的部分。
const jchar *str=jEnv->GetStringChars(jArg2,0);
WideCharToMultiByte(CP_UTF8,0,(LPCWSTR) str,jEnv->GetStringLength(jArg2),str,szStr,0,0);
const jchar *str = jEnv->GetStringChars(jArg2,0);
char *cp1252 = NULL;
int len = WideCharToMultiByte(1252, 0, (LPCWSTR)str, jEnv->GetStringLength(jArg2), NULL, 0, 0, 0);
if (len > 0)
{
cp1252 = new char[len + 1];
WideCharToMultiByte(1252, 0, (LPCWSTR)str, jEnv->GetStringLength(jArg2), cp1252, len, 0, 0);
cp1252[len] = 0;
}