Devexpress 如何从Unicode数据库加载TMemoryStream

Devexpress 如何从Unicode数据库加载TMemoryStream,devexpress,c++builder-2010,Devexpress,C++builder 2010,我试图用计算的RTF文件字符串填充DevExpress VCLTdxRichEditControl,而不花时间保存文件。下面是一个演示项目: void\uu fastcall TForm1::Button1Click(TObject*Sender) { UnicodeString txt=“{\\rtf1\\deff0{\\fonttbl{\\f0 Calibri;}{\\f1 Arial Unicode MS;}{\\f2 Britanic Bold;}}{\\colortbl;\\red0\

我试图用计算的RTF文件字符串填充DevExpress VCL
TdxRichEditControl
,而不花时间保存文件。下面是一个演示项目:

void\uu fastcall TForm1::Button1Click(TObject*Sender)
{
UnicodeString txt=“{\\rtf1\\deff0{\\fonttbl{\\f0 Calibri;}{\\f1 Arial Unicode MS;}{\\f2 Britanic Bold;}}{\\colortbl;\\red0\\green0\\blue255;\\red255\\green0\\blue0;}{\*\\defchp\\fs22}{\\\\*\\defpap\\sl275\\slmult1\\sa200}{\\stylesheet{\\ql\\sl275 slmult1\\sa200\\fs22正常;\\\\\\\cs1\\fs22默认段落}{{\\\\\\cs2\\sbasedon1\\fs22行号;}{\\\\\\\cs3\\ul\\fs22\\cf1超链接;}{\\\\\\\ts4\\tsrowd\\fs22\\ql\\sl275\\slmult1\\sa200\\tscellpaddfl3\\tscellpaddl108\\tscellpaddfr3\\tscellpaddr108\\tscellpaddft3\\tsvertalt\\cltxlrtb正常表;}{\\*\\ts5\\tsrowd\\sbasedon4\\fs22\\ql\\slmult1\\sa200\\trbrdrt\\brdrs\\brdrw10\\trbrdrl\\brdrs\\brdrw10\\trbrdrb\\brdrs\\brdrw10\\trbrdrr\\brdrs\\brdrw10\\trbrdrh\\brdrs\\brdrw10\\trxlbrdrv\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrw10\\tscelllpaddl108\\tscelllfr3\\paddl108\\trtrtrtrdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\brdrs\\\\nouicompat\\splytwnine\\htmautsp\\sectd\\pard\\plain\\ql\\sl275\\slmult1\\sa200{\\f1\\fs28\\cf1这是蓝色的}{\\b\\i\\f2\\fs40\\cf2红色粗体}\\b\\i\\fs22\\cf2\\par}”;
TMemoryStream*AStream=newtmemoryStream();
AStream->WriteBuffer(txt.c_str(),txt.Length());
AStream->Position=0;
AStream->SaveToFile(“C:/Trash/Test.rtf”);
AStream->Position=0;
dxRichEditControl1->文档->插入文档内容(dxRichEditControl1->文档->范围->开始,AStream,TdxRichEditDocumentFormat::Rtf);
AStream->Free();
}
在这个演示中,我将其保存到一个文件中,以查看出现了什么问题,并发现该文件中每隔一个字符都包含一个空格(因此,当然,我试图填充此数据的组件没有显示任何内容)。当我查看该文件时,我看到的是这种类型的内容:

{ \ r t f 1 \ d e f f 0 { \ f o n t t b l { \ f 0   C a l i b r i ; } { \ f 1   A r i a l   U n i c o d e   M S ; } { \ f 2   B r i t a n n i c   B o l d ; } } { \ c o l

我想坚持将txt变量存储为UnicodeString,因为实际项目中有一个计算该字符串的类,但是有没有解决这个问题的方法?我意识到我可能会做一些耗时的事情,比如循环并消除其他字符,但我需要一些有效的解决方案。

RTF是一个7位的ASCII格式,因此您根本不应该将其视为UTF-16。正确的解决方案是将
UnicodeString
更改为
ansisting

AnsiString txt=。。。;
“额外空格”是由于在UTF-16中将7位ASCII字符扩展为16位值时添加了
0x00
字节

此外,您甚至没有正确地将
UnicodeString
写入
TMemoryStream
。由于
WriteBuffer()
处理原始字节,而不是字符串字符,因此需要将
txt.Length()
乘以
sizeof(System::WideChar)
以获得正确的字节计数:

UnicodeString txt=。。。;
...
AStream->WriteBuffer(txt.c_str(),txt.Length()*sizeof(WideChar));
如果更改为
AnsiString
,则不需要乘法,因为
sizeof(AnsiChar)
是1

但是,如果设置为坚持使用
UnicodeString
,则至少使用
TStringStream
,以便为其指定字节编码:

UnicodeString txt=。。。;
TStringStream*AStream=新的TStringStream(txt,TEncoding::ASCII);
...

另外,由于流是使用
new
创建的,因此应该将
AStream->Free();
改为
delete AStream;
。切勿调用
TObject::Free()在C++中,C++直接使用了一种Delphi的成语。用C++方式释放分配给<代码>新< /代码>的东西是<代码>删除< /代码>。它将调用“代码> ToStudio< /Case>析构函数,正如<代码> ToStudi::/Field> < /P> > ./P>谢谢ReMy。根据您的答案,我找到了一个简单的答案。“AnsiString txtAnsi=UTF8Encode(txt);”并将“txt”的其他引用更改为“txtAnsi”“。它可能会浪费一点时间/空间,但这是一个快速而肮脏的解决方案。将UTF-8字符串分配给
AnsiString
将UTF-8数据转换为ANSI,而ANSI仅对ASCII字符是无损的。在这种情况下,这只是一种浪费的转换。
UTF8Encode()自从C++Builder 2009引入
UnicodeString
以来,就不推荐使用
UnicodeString
。如果您真的想将
UnicodeString
转换为UTF-8字符串,只需使用
UTF8String
即可:
UTF8String txtUtf8=txt;
但这确实是不必要的,因为
TStringStream
可以对
unicode>进行编码在内存中没有ASCII/ANSI/UTF8数据的两个副本的情况下将
数据转换为ASCII/ANSI/UTF8。我在TStringStream中遇到问题。构造函数有第三个布尔参数,在Delphi中是可选的(默认为true)在C++中,需要在参数中设置true或false,这两个结果在我的示例程序中都是相同的结果。与使用
UnicodeString
TEncoding::UTF8
创建
TStringStream
相比,
TStringStream
构造函数只需将
UnicodeString
转换为UTF-8字节数组,并让基
TMemoryStream
拥有它。您可以轻松验证这两种类型的streams产生相同的数据。对于标准的
TEncoding
编码,如
TEncoding::UTF8
,第三个构造函数参数被忽略。