2017-03-16 18 views
0

我正在使用gSoap和C++来发送和接收来自Java的Web服务调用。 Java认为一个字符和C/C++认为一个字符的差别似乎在破坏浩浩荡荡,就像不同的代码页一样。这个问题有几个不同的部分。从Java SOAP接收的Windows调用(C++)中使用Unicode文本

  1. 我读过Java存储内存中的字符串为UTF-16和磁盘为UTF-8。当我将Java字符串发送到C++客户端时,我应该假设它是UTF-8还是UTF-16?
  2. 当我从Java收到一个字符串并将其插入到std::wstring中时,没有任何转换,C++客户端使用Windows-1252代码页。是否接收并转换Unicode字符串MultiByteToWideChar的正确功能?
  3. 虽然我调用的Windows函数(SetComputerNameExW)旨在接受Unicode,但是当我传入通过SOAP从Java接收的字符串时(我特别在调试时将字符串重新编码为UTF-8)请求和在C++端将其解码为UTF-8,在将值传递给SetComputerNameExW后,系统启动重新启动,但仅将机器重命名为第一个字符(即,如果我的字符串是ThisIsATëst,则机器将重命名为T)。是否有一个特定的Unicode格式必须用于这些Windows API调用?

任何援助非常感谢!谢谢!

+0

_“...和磁盘上的UTF-8”_这通常取决于您使用的IO API的编码。 –

+0

Windows使用UTF-16LE。如果您在Java中使用UTF-16字符串,只需将它们传递给Windows即可。如果您将它们保存为UTF-8,则在将它们读入Windows程序时,您需要将它们转换为UTF-16LE。 'MultiByteToWideChar'可以从UTF-8转换为UTF-16,所以C++ 11的标准功能可以。 –

回答

1

我已阅读,在内存中的Java存储字符串作为UTF-16

使用,但这种情况正在改变。根据JEP 254: Compact Strings,内存中的存储可能很快会使用ISO-8859-1,但是只有在时才会产生比UTF-16更紧凑的存储而不会丢失数据。尽管Java字符串使用基于UTF-16的公共接口(不管它们的内存中存储是否使用ISO-8859-1)。所以只是假装他们总是UTF-16。

当我有一个Java字符串被发送到C++客户端,我应该假设它是UTF-8或UTF-16吗?

你也不能假设。你必须看看实际的SOAP数据。 SOAP使用XML,并且XML可以使用任何编码创建者想要的字符,只要它在XML prolog中声明它(如果它不是UTF-8,它是XML中最常用的编码)。不要假设,知道你在做什么。如果您使用的是SOAP库,则受限于其选择用于其内存字符串的任何编码。

当我收到从Java一个字符串,然后将其插入std::wstring,没有任何类型转换的C++客户端使用Windows-1252代码页。

这是不太可能的,因为std::wstring在Windows上使用UTF-16,并且Java字符串也是UTF-16(用于所有意图和目的)。您必须错误地转换您的字符串。请edit your question显示您的实际代码。

接收和转换Unicode字符串MultiByteToWideChar是否正确?

IF你有一个8位ANSI字符串开始与(char*std::string),然后是。但是,当与Java直接交互(通过JNI/JNA)或std::wstring时,情况不应该如此。所以这让我想知道是否在基于8位ANSI字符串而不是16位Unicode字符串的C++端使用SOAP实现。

虽然,我调用Windows函数(SetComputerNameExW)是指接受Unicode的,当我传递一个从Java通过SOAP收到的字符串(我特意重新编码字符串作为UTF-8,而调试)请求,并将它,解码为对C++侧UTF-8的值传递给SetComputerNameExW系统之后启动一个重新启动

不能在UTF-8字符串传递给SetComputerNameExW(),代码甚至不会编译,除非你使用无效的类型转换强制它。您必须改为传递一个UTF-16字符串。

但只重命名机器的第一个字符(即,如果我的字符串为ThisIsATëst,那么机器将重命名为T)。

这意味着某些事情对您的转换非常不利。无论你认为你传递到SetComputerNameExW()是不是什么实际上被传递,它没有正确格式化,这就是为什么SetComputerNameExW()只拿起第一个字符。

但是,再次,这是一种情况,您没有显示您的实际SOAP数据或代码,所以没有人可以告诉你为什么字符串未被正确格式化。

是否有一个特定的Unicode格式必须用于这些Windows API调用?

的Win32 API中只支持两种类型的字符串:

  • 本地化的ANSI字符串

  • UTF-16字符串

不能使用UTF-8 (除非是很少的情况),所以你必须将任何UTF-8数据转换为其他格式之一(最好是UTF-16,因为之间的转换UTF无损,Windows核心基于UTF-16)。

+0

令人惊叹的答案,非常感谢和非常好的阐述。荣誉。 – clamport