delphi 操作 utf-8 的xml 有乱码的解决
来源:互联网 发布:雷洋案真相知乎 编辑:程序博客网 时间:2024/06/05 02:07
这两天要用delphi 做个东西要与 xml相关, 开始只是想用 delphi本身的控制,网上找了下, 有两种方式,一个是 TXMLDocument 在 Internet 面板下, 另一个是用 IXMLDomDocument 需要用到 单元文件 msxml, 开始只注意到英文,用 TXMLDocument 解析起来没什么问题, 但是后来要涉及到多语言问题, xml文件是 utf-8格式,用 TXMLDocumnet解析的时候,就成了乱码,这两天在网上找了好久,都没成功(我的开发环境是英文的, 王哥说delphi支持 utf-8的xml, 而我照着他的例子一直都没成功, 很闷.后来晚上回家在中文环境下实验时,一切正常...) , 网上看到, delphi处理 utf-8时,需要转成ansi编码 (WideString 还是 AnsiString ?谈谈字符编码)
我按这种方式转了之后, 然后继承 TXMLDocument 使 其的 loadFromXml 可用, 但是结果报错, 因为字符串的编码和encoding的编码不一致, 一直没有进展, 也考虑过用 msxml, 但初步使用之后还是乱码. 但却没想到先转码, 然后通过 msxml的方式...
今天上午无意中用了 IXMLDomDocument 来解析, 不过在解析之前先把文件当做文本读出来并转码, 然后再解析, 终于, 成功了.
有两个部分要注意, 一是转码, 我直接抄网上的, 后面会出来, 另一部分则是用 ixmlDomDocument 解析.
temp.xml 注意保存为 utf-8格式, 记事本-->保存-->下面选择 utf-8
- <?xml version="1.0" encoding="utf-8" standalone="no"?>
- <root maxnodeId="15">
- <node objid="1" name="発注-H" >
- <subnode objid="1" name="oid" />
- <subnode objid="6" name="発注番号 :" />
- <subnode objid="7" name="発注状況 :" />
- <subnode objid="72" name="入荷状況 :"/>
- <subnode objid="76" name="買掛状況 :" />
- <subnode objid="8" name="発注日 :" type="date" />
- <subnode objid="73" name="入荷日 :" type="date" />
- <subnode objid="77" name="离开时间:" type="date" />
- <subnode objid="8" name="発注日 :" type="date" />
- <subnode objid="73" name="入荷日 :" type="date" />
- <subnode objid="77" name="支払日 :" type="date" />
- <subnode objid="79" name="請求額 :" type="int" />
- </node>
- </root>
encoding.pas 这个主要是参照下面那个 wideString or AnsiString的
- unit encoding;
- interface
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics,
- Controls, Forms, Dialogs, ComCtrls, Menus, StdCtrls;
- Type
- TEncodeFlags = (efUnknown, efAnsi, efUnicode, efUncodeBigEn, efUTF8);
- TTextFormat=(tfAnsi,tfUnicode,tfUnicodeBigEndian,tfUtf8);
- TUTF8Falg = packed record
- EF, BB, BF: Byte;
- end;
- const
- TextFormatFlag:array[tfAnsi..tfUtf8] of word=($0000,$FFFE,$FEFF,$EFBB);
- Encode: TUTF8Falg = (EF: $EF; BB: $BB; BF: $BF);
- function ChWideToAnsi(const StrW: WideString): AnsiString;
- function ChAnsiToWide(const StrA: AnsiString): WideString;
- function UTF8ToWideString(const Stream: TStream): WideString;
- procedure TextToUTF8Stream(const Text: string; var Stream: TStream);
- function GetEncodeFromStream(const Stream: TStream): TEncodeFlags;
- function loadFromFile(const fName :string) :String;
- procedure savetoFile(const txt, fName :String);
- implementation
- function loadFromFile(const fName :String) :String;
- var
- FStream :TStream;
- begin
- FStream := TMemoryStream.Create;
- TMemoryStream(FStream).LoadFromFile(fName);
- if GetEncodeFromStream(FStream) = efUTF8 then
- begin
- result := ChWideToAnsi(UTF8ToWideString(FStream));
- end;
- end;
- procedure savetoFile(const txt, fName :String);
- var
- FStream :TStream;
- begin
- FStream := TMemoryStream.Create;
- try
- TextToUTF8Stream(txt, FStream);
- TMemoryStream(FStream).SaveToFile(fName);
- finally
- FStream.Size := 0;
- end;
- end;
- procedure WordLoHiExchange(var w:Word);
- var
- b:Byte;
- begin
- b:=WordRec(w).Lo;
- WordRec(w).Lo:=WordRec(w).Hi;
- WordRec(w).Hi:=b;
- end;
- function ChWideToAnsi(const StrW: WideString): AnsiString;
- var
- nLen: integer;
- begin
- Result := StrW;
- if Result <> '' then
- begin
- nLen := WideCharToMultiByte(936, 624, @StrW[1], -1, nil, 0, nil, nil);
- SetLength(Result, nLen - 1);
- if nLen > 1 then
- WideCharToMultiByte(936, 624, @StrW[1], -1, @Result[1], nLen - 1, nil, nil);
- end;
- end;
- function ChAnsiToWide(const StrA: AnsiString): WideString;
- var
- nLen: integer;
- begin
- Result := StrA;
- if Result <> '' then
- begin
- nLen := MultiByteToWideChar(936, 1, PChar(@StrA[1]), -1, nil, 0);
- SetLength(Result, nLen - 1);
- if nLen > 1 then
- MultiByteToWideChar(936, 1, PChar(@StrA[1]), -1, PWideChar(@Result[1]), nLen - 1);
- end;
- end;
- function UTF8ToWideString(const Stream: TStream): WideString;
- var
- nLen: Cardinal;
- begin
- try
- SetLength(Result, Stream.Size div SizeOf(WideChar) * 3);
- nLen := Utf8ToUnicode(@Result[1], Length(Result),
- Pointer(DWord(TMemoryStream(Stream).Memory) + Stream.Position),
- Stream.Size - Stream.Position);
- SetLength(Result, nLen);
- except
- SetLength(Result, 0);
- end;
- end;
- procedure TextToUTF8Stream(const Text: string; var Stream: TStream);
- var
- StringW, StrW: WideString;
- nLen: Cardinal;
- begin
- try
- if Text <> '' then
- begin
- StrW := ChAnsiToWide(Text);
- nLen := Length(StrW) * 3;
- SetLength(StringW, nLen);
- nLen := UnicodeToUtf8(@StringW[1], nLen, @StrW[1], Length(StrW));
- SetLength(StringW, nLen);
- Stream.Write(Encode, SizeOf(Encode));
- Stream.Write(StringW[1], Length(StringW));
- end
- else
- Stream.Write(Encode, SizeOf(Encode));
- except
- SetLength(StrW, 0);
- SetLength(StringW, 0);
- end;
- end;
- function GetEncodeFromStream(const Stream: TStream): TEncodeFlags;
- var
- FEncode: TUTF8Falg;
- begin
- Result := efUnknown;
- Stream.Read(FEncode, SizeOf(FEncode));
- if (FEncode.EF = Encode.EF) and (FEncode.BB = Encode.BB)
- and (FEncode.BF = Encode.BF) then Result := efUTF8;
- end;
- end.
下面是使用代码,你可以直接拷到一个 button的事件中
- var
- xmlDom :IXMLDomDocument;
- begin
- xmlDom := msxmldom.CreateDOMDocument;
- xmlDom.loadXML(encoding.loadFromFile('temp.xml'));
- showMessage(xmlDom.xml);
- end;
试的环境有, 英文,中文(简体), 中文(台湾), 日语, 朝鲜语, 其中前三者都完成正确,但是后两个有部分不能正常显示,有待考虑.
特别感谢: 王哥的帮助 http://hi.csdn.net/zswang/
另外还参考了 WideString 还是 AnsiString ?谈谈字符编码
http://blog.csdn.net/xwchen/archive/2007/03/21/1536829.aspx
encoding部分是从这来的
- delphi 操作 utf-8 的xml 有乱码的解决
- delphi 操作 utf-8 的xml 有乱码的解决
- mysql utf-8乱码的解决
- Tomcat的解决UTF-8乱码
- 【原创】JDom输出UTF-8的XML完美解决(中文乱码的原因分析)
- JDom输出UTF-8的XML出现中文乱码完美解决
- 解决采集UTF-8出现乱码的问题
- 解决UltraEdit在UTF-8下的乱码问题
- Apache Commons FileUpload使用UTF-8时乱码的解决
- 完美解决mysql下utf-8的乱码问题
- Windows下解决GVIM的UTF-8乱码
- PHP echo utf-8 中文 乱码问题的解决
- 解决UltraEdit在UTF-8下的乱码问题
- 解决mysql下utf-8的乱码问题
- thinkPHP读取数据库的utf-8中文乱码解决
- 完美解决mysql下utf-8的乱码问题
- 完美解决mysql下utf-8的乱码问题
- thinkPHP读取数据库的utf-8中文乱码解决
- Oracle 函数大全(字符串函数,数学函数,日期函数,逻辑运算函数,其他函数)
- DataColumn 类
- 函数指针和C#代理
- 三猪版opera9.62发布~~
- 本人自己写的一个银行系统
- delphi 操作 utf-8 的xml 有乱码的解决
- ToString()、Convert.ToString()、(string)、as string 的区别
- 在ASP.NET 2.0中开发通配符映射应用程序的一些问题
- jfreechart web例子
- Microsoft Platform SDK 选择
- LinkedIn 架构笔记
- 主题:让Hsqldb随WebAPP一起启动
- 硬件工程师"要求"
- ofbiz的配置文件位置