2012-12-14 44 views
0

我似乎将一个字节数组(包含word文档中的文本)转换为LPTSTR(wchar_t *)对象时出现问题。每次执行代码时,我都会收到一些不需要的Unicode字符。将字节数组的内容转换为wchar_t *

我想这是因为我没有正确调用某个地方,或者没有正确使用变量,但不太清楚如何处理这个问题。希望这里有人能指导我朝着正确的方向前进。

第一件事发生在我们调用C#代码来打开Microsoft Word并将文档中的文本转换为字节数组。是

byte document __gc[]; 
document = word->ConvertToArray(filename); 

的文件内容如下:

{84, 101, 115, 116, 32, 68, 111, 99, 117, 109, 101, 110, 116, 13, 10} 

这最终是以下字符串: “测试文档”。

我们下一步是一旦我们执行我们开始分配内存行分配给字节数组存储到一个LPTSTR变量的内存,

byte __pin * value; 

value = &document[0]; 

LPTSTR image; 
image = (LPTSTR)malloc(document->Length + 1); 

,我们的形象变量被装满一堆不需要的Unicode字符:

췍췍췍췍췍췍췍췍﷽﷽����˿於潁 

然后我们做的memcpy转移了所有的数据

memcpy(image,value,document->Length); 

刚刚引起更多不必要的Unicode字符显示:

敔瑳䐠捯浵湥൴촊﷽﷽����˿於潁 

我想,我们遇到的问题或者是关系到我们如何存储字节数组中的值,或可能,当我们在数据复制从字节数组到LPTSTR变量。任何帮助解释我做错了什么,或任何指向我在正确的方向将不胜感激。

+0

“每次执行代码时,都会得到一串返回的Unicode字符”您知道Windows上的wchar_t是_supposed_是Unicode,对吧? Windows使用UTF-16作为其wchar_t编码。 – bames53

+0

所有字符都是Unicode字符。 – melpomene

+1

'memcpy'不是在char和wchar_t之间进行转换的适当方式......它根本不做任何转换。 – bames53

回答

5

首先,您应该了解一些关于文本数据以及它如何表示的内容。这将让你的引用开始有The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

byte,不过是为了charunsigned char的typedef或东西。所以字节数组对字符串使用了一些char编码。您需要实际将该编码转换为适用于Windows的编号为wchar_t的UTF-16。这里推荐在Windows上做这种转换的典型方法:

int output_size = MultiByteToWideChar(CP_ACP,0,value,-1,NULL,0); 
assert(0<output_size); 
wchar_t *converted_buf = new wchar_t[output_size]; 
int size = MultiByteToWideChar(CP_ACP,0,value,-1,converted_buf,output_size); 
assert(output_size==size); 

我们调用函数MultiByteToWideChar()两次,一次弄清楚持有转换的结果是多么大的缓冲区的需要,而第二次,传入我们分配的缓冲区,进行实际的转换。

CP_ACP指定了源编码,您需要检查API文档以确定该值应该是多少。 CP_ACP代表'代码页:Ansi代码页',这是微软对'非Unicode'程序编码集的说法''。该API可能会使用其他的东西,如CP_UTF8(我们可以希望)或1252或其他东西。

您可以查看MultiByteToWideChar here上的其余文档以找出其他参数。


一旦我们执行我们开始分配内存行了,我们的形象变量被装满了一堆不必要的Unicode字符:

当你打电话malloc()给你的内存是未初始化,只是包含垃圾。你在初始化之前看到的值并不重要,你根本不应该使用这些数据。唯一重要的数据就是填充缓冲区的数据。上面的MultiByteToWideChar()代码也会自动终止字符串,所以你不会在未使用的缓冲区空间中看到垃圾(我们用来分配缓冲区的方法不会留下任何额外的空间)。


上面的代码实际上并不是很好的C++风格。这只是Win32提供的C风格API的典型用法。我喜欢做转换(如果我被迫)的方式更像是:

使用
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert; // converter object saved somewhere 

std::wstring output = convert.from_bytes(value); 

(假设char编码是UTF-8,您将不得不使用不同的codecvt方面的任何其他编码)。

+0

出于兴趣,是否有任何Windows代码页面的单个字节/代码点可能需要多个UTF-16代码单元?我同意两次打电话给MBTWC是正确的,我只是模糊地好奇,结果是不可预知的:-) –

+0

@SteveJessop是的,CP_UTF8。另一个问题是Windows上是否有任何语言环境的代码页支持需要代理代码点的任何字符;我不知道答案,但是如果存在的话,这违反了标准(C++ 11§3.9.1/ 5)。 – bames53

+0

糟糕,我应该指定一个代码页*,可能是CP_ACP *。我得到的是,如果你通过CP_ACP,或者在这种情况下MultiByteToWideChar相当于'strlen(value)+ 1',那么测量结果实际上是否会返回比字符串长度更多的值呢?听起来答案是后者,假设MS符合标准。 –