delphi 操作 utf-8 的xml 有乱码的解决

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

   说明下,这个方法有好大的缺陷,XML必须要严格正确,如果有什么特殊字符,会导致出错,其次,并不能很好的解决日文或韩文问题,我已经换成了c#了

 

这两天要用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
    1. <?xml version="1.0" encoding="utf-8" standalone="no"?>
    2. <root maxnodeId="15">
    3.   <node objid="1" name="発注-H" >
    4.     <subnode objid="1" name="oid" />
    5.     <subnode objid="6" name="発注番号 :" />
    6.     <subnode objid="7" name="発注状況 :"  />
    7.     <subnode objid="72" name="入荷状況 :"/>
    8.     <subnode objid="76" name="買掛状況 :" />
    9.     <subnode objid="8" name="発注日 :" type="date" />
    10.     <subnode objid="73" name="入荷日 :" type="date" />
    11.     <subnode objid="77" name="离开时间:" type="date" />
    12.     <subnode objid="8" name="発注日 :" type="date" />
    13.     <subnode objid="73" name="入荷日 :" type="date" />
    14.     <subnode objid="77" name="支払日 :" type="date" />
    15.     <subnode objid="79" name="請求額 :" type="int" />
    16.   </node>
    17. </root>
encoding.pas 这个主要是参照下面那个 wideString or AnsiString的

  1. unit encoding;
  2. interface
  3.  uses
  4.   Windows, Messages, SysUtils, Variants, Classes, Graphics,
  5.  Controls, Forms, Dialogs, ComCtrls, Menus, StdCtrls;
  6. Type
  7. TEncodeFlags = (efUnknown, efAnsi, efUnicode, efUncodeBigEn, efUTF8);
  8. TTextFormat=(tfAnsi,tfUnicode,tfUnicodeBigEndian,tfUtf8);
  9. TUTF8Falg = packed record
  10.    EF, BB, BF: Byte;
  11.  end;
  12. const
  13. TextFormatFlag:array[tfAnsi..tfUtf8] of word=($0000,$FFFE,$FEFF,$EFBB);
  14. Encode: TUTF8Falg = (EF: $EF; BB: $BB; BF: $BF);
  15.    function ChWideToAnsi(const StrW: WideString): AnsiString;
  16.    function ChAnsiToWide(const StrA: AnsiString): WideString;
  17.    function UTF8ToWideString(const Stream: TStream): WideString;
  18.    procedure TextToUTF8Stream(const Text: stringvar Stream: TStream);
  19.    function GetEncodeFromStream(const Stream: TStream): TEncodeFlags;
  20.     
  21.    function loadFromFile(const fName :string) :String;
  22.    procedure savetoFile(const txt, fName :String);
  23. implementation
  24. function loadFromFile(const fName :String) :String;
  25. var
  26.   FStream :TStream;
  27. begin
  28.     FStream := TMemoryStream.Create;  
  29.  TMemoryStream(FStream).LoadFromFile(fName);
  30.  if GetEncodeFromStream(FStream) = efUTF8 then
  31.  begin
  32.    result := ChWideToAnsi(UTF8ToWideString(FStream));
  33.  end;
  34. end;
  35. procedure savetoFile(const txt, fName :String);
  36. var
  37.   FStream :TStream;
  38. begin
  39.     FStream := TMemoryStream.Create;  
  40.   try
  41.     TextToUTF8Stream(txt, FStream);
  42.     TMemoryStream(FStream).SaveToFile(fName);
  43.   finally
  44.     FStream.Size := 0;
  45.   end;
  46. end;
  47. procedure WordLoHiExchange(var w:Word);
  48. var
  49. b:Byte;
  50. begin
  51.   b:=WordRec(w).Lo;
  52.   WordRec(w).Lo:=WordRec(w).Hi;
  53.   WordRec(w).Hi:=b;
  54. end;
  55.     
  56. function ChWideToAnsi(const StrW: WideString): AnsiString;
  57. var
  58.  nLen: integer;
  59. begin
  60.  Result := StrW;
  61.  if Result <> '' then
  62.  begin
  63.    nLen := WideCharToMultiByte(936624, @StrW[1], -1nil0nilnil);
  64.    SetLength(Result, nLen - 1);
  65.    if nLen > 1 then
  66.      WideCharToMultiByte(936624, @StrW[1], -1, @Result[1], nLen - 1nilnil);
  67.  end;
  68. end;
  69. function ChAnsiToWide(const StrA: AnsiString): WideString;
  70. var
  71.  nLen: integer;
  72. begin
  73.  Result := StrA;
  74.  if Result <> '' then
  75.  begin
  76.    nLen := MultiByteToWideChar(9361, PChar(@StrA[1]), -1nil0);
  77.    SetLength(Result, nLen - 1);
  78.    if nLen > 1 then
  79.      MultiByteToWideChar(9361, PChar(@StrA[1]), -1, PWideChar(@Result[1]), nLen - 1);
  80.  end;
  81. end;
  82. function UTF8ToWideString(const Stream: TStream): WideString;
  83. var
  84.  nLen: Cardinal;
  85. begin
  86.  try
  87.    SetLength(Result, Stream.Size div SizeOf(WideChar) * 3);
  88.    nLen := Utf8ToUnicode(@Result[1], Length(Result),
  89.      Pointer(DWord(TMemoryStream(Stream).Memory) + Stream.Position),
  90.      Stream.Size - Stream.Position);
  91.    SetLength(Result, nLen);
  92.  except
  93.    SetLength(Result, 0);
  94.  end;
  95. end;
  96. procedure TextToUTF8Stream(const Text: stringvar Stream: TStream);
  97. var
  98.  StringW, StrW: WideString;
  99.  nLen: Cardinal;
  100. begin
  101.  try
  102.    if Text <> '' then
  103.    begin
  104.      StrW := ChAnsiToWide(Text);
  105.      nLen := Length(StrW) * 3;
  106.      SetLength(StringW, nLen);
  107.      nLen := UnicodeToUtf8(@StringW[1], nLen, @StrW[1], Length(StrW));
  108.      SetLength(StringW, nLen);
  109.      Stream.Write(Encode, SizeOf(Encode));
  110.      Stream.Write(StringW[1], Length(StringW));
  111.    end
  112.    else
  113.      Stream.Write(Encode, SizeOf(Encode));
  114.  except
  115.    SetLength(StrW, 0);
  116.    SetLength(StringW, 0);
  117.  end;
  118. end;
  119. function GetEncodeFromStream(const Stream: TStream): TEncodeFlags;
  120. var
  121.  FEncode: TUTF8Falg;
  122. begin
  123.  Result := efUnknown;
  124.  Stream.Read(FEncode, SizeOf(FEncode));
  125.  if (FEncode.EF = Encode.EF) and (FEncode.BB = Encode.BB)
  126.    and (FEncode.BF = Encode.BF) then Result := efUTF8;
  127. end;
  128. end.

下面是使用代码,你可以直接拷到一个 button的事件中

  1. var
  2.   xmlDom :IXMLDomDocument;
  3. begin
  4.   xmlDom := msxmldom.CreateDOMDocument;
  5.   xmlDom.loadXML(encoding.loadFromFile('temp.xml'));
  6.   showMessage(xmlDom.xml);
  7.  end;


试的环境有, 英文,中文(简体), 中文(台湾), 日语, 朝鲜语, 其中前三者都完成正确,但是后两个有部分不能正常显示,有待考虑.

特别感谢: 王哥的帮助 http://hi.csdn.net/zswang/

另外还参考了 WideString 还是 AnsiString ?谈谈字符编码
http://blog.csdn.net/xwchen/archive/2007/03/21/1536829.aspx
encoding部分是从这来的
DelphiXe8 FTP客户端程序解决中文乱码问题增加进度条功能 DelphiXe8 FTP客户端程序解决中文乱码问题增加进度条功能,xe8编译通过!其它的自行设置。需要的就下吧。 立即下载

相关推荐

Delphi XE 10.3.3 TFileStream读read写write字符串必须用UTF8String防止出现垃圾字符

最近需要将一个Delphi 7的古老程序重构升级为Delphi 10.3.3,没想到由于Delphi字符串定义发生了变化,造成写入文件的字符串出现垃圾字符 我有Delphi 2007代码看起来像这样: procedure WriteString(Stream: TFileStream; var SourceBuffer: PChar; s: string); begin StrPCopy(SourceBuffer,s); Stream.Write(SourceBuffer[0], StrLen

Delphi开发局QQ群:32422310 2301

Delphi2010中保存UTF8/Unicode编码文件的问题

使用Delphi2010中的TStrings或Memo的SaveToFile方法保存UTF8/Unicode编码的字符串时,保存后丢失编码信息,仔细查看,原来在保存时增加了编码设置: aStrings.SaveToFile(aFileName,TEncoding.Unicode) ;//可以是TEncoding.UTF8,根据需要   另: unicode文本文件:头两个字符分别是FF  ...

weixin_34367845的博客 424

Delphi 中使用TFileStream以二进制方式保存文本文件注意事项

使用TFileStream 保存文本文件的一些注意事项

staryy的专栏 5806

关于delphiXE中使用idhttp下载带有中文的文件解决方法。

delphi7中使用idhttp下载中文文件没有问题,但是在delphiXE中下载带有中文的文件就有问题。这是因为在delphiXE中的string类型占用的字节不一样照成的, 解决方法,在request之前对url进行编码 idHTTP.URL.URLEncode(fileurl) 。例子如下: 这个是下载的函数; procedure TForm3.Button2Click(Se

lenovo455的专栏 3833

DELPHIUTF8保存,读取

procedure TForm1.btn1Click(Sender: TObject); var   AfileStream:TFileStream;   Autf8Bytes:string ;   s:string; begin   AfileStream:=TFileStream.Create('c:\abc.txt',fmCreate);   try     Autf8Byt

shandiantianying的专栏 1781

delphi 操作 utf-8xml乱码解决

  这两天要用delphi 做个东西要与 xml相关, 开始只是想用 delphi本身的控制,网上找了下, 有两种方式,一个是 TXMLDocument 在 Internet 面板下, 另一个是用 IXMLDomDocument 需要用到 单元文件  msxml, 开始只注意到英文,用 TXMLDocument 解析起来没什么问题,  但是后来要涉及到多语言问题, xml文件是 utf-8格式,用

三岔路口,每一条路都有自己的精彩...... 5815

delphi NativeXml的中文支持 乱码

一般XML的编码格式设置成UTF8比较通用,下面演示使用UTF8编码方式存储和处理包含中文的XML字符串(文件)。1.设置启用内置的widestring支持NativeXml内部使用ANSI stringUTF8编码的string两种字符串类型。如果要让NativeXml能够解析widestring字符串的话,直接将TNativeXmlUtf8Encoded属性设置为True。如下:FXm...

a6636319的博客 457

解决Delphi XML-RPC 中文乱码、结构/数组等没有解析I4项BUG

 最近要用XML-RPC机制实现delphi程序与Qt程序之间的通信,从开源网站http://sourceforge.net/projects/delphixml-rpc/下载Delphi XML-RPC 后发现中文字符串会出现乱码,跟踪代码后发现XML-RPC默认的字符编码是UTF-8,而且QT也都是用UTF-8编程,故把传输字符串改为UTF-8就行了,修改方法:一、单元XmlRpcTypes.pas     1、修改TRpcFunction类中的三个函数:GetRequestXML、GetRespons

csm2432的专栏 2429

delphi html 乱码,delphi utf8乱码问题

其中的utf8是一种常用的unicode编码方式,在目前的网络环境中应用最广,特别是在java,xml这种国际化很强的地方.delphi并不支持原生的utf8字符串,它对unicode的支持则是非常好了.将普通字符串赋值给String类型即可.而对uft8则要用到上面所说的Utf8ToAnsi等转换函数.好在这些函数都很容易使用,只是大家在使用时要注意自己当前操作的字符串是什...

weixin_36056010的博客 920

TXMLDOCUMENT读取UTF-8格式XML文件乱码问题

学习点滴 记录点滴。。。========================================================= var   XMLDocument:TXMLDocument;   XMLNode :IXMLNode;begin  XMLDocument:=TXMLDocument.Create(self);  XMLDocument.Load

genispan的专栏 4729

delphi IXMLDocument 解析xml 异常。

最近在用delphi解析xml,使用的是UTF-16编码,含中文。 做例子测试: Form包含一个Button,两个Memo。 procedure TForm1.Button1Click(Sender: TObject);var xmldocument1:IXMLDocument; xmlstr:string;begin xmlstr:=memo1.Lines.te...

weixin_30512043的博客 471

delphiutf-8

var  S:UTF8String;  with TMemoryStream.Create do      try       LoadFromFile(ExtractFilePath(ParamStr(0))+'01C82Write.xml');       SetLength(S, Size);       Read(S[1], Length(S));       s := Utf8ToAns

259

XML中文显示问题

XML默认的编码格式是UTF-8,这种编码模式不显示汉字,所以经常有些初学者会遇到XML中汉字不 能显示的问题,出现如下错误提示:An invalid character was found in text content... 【解 决方法】:将encoding设为GB2312,即 ,这样编码格式就被设置成简体中文了。       当XML文件的数据与编码不符合的时候,就可能发生无法正确解译

thislocal的博客 2009

Delphi语音通知接口集成方案:Delphi开发者如何快速对接语音告警API组件

本文针对Delphi开发者对接语音通知接口的痛点,提供了两种实战集成方案。核心解决了HTTP组件适配、加密处理、参数校验等关键问题,包含静态密码POST方式和动态密码模板变量方式两种实现。通过封装可复用的Delphi单元,开发者可快速集成语音告警功能,兼容Delphi 10.4及以上版本,有效降低开发复杂度并提升系统稳定性。文中代码示例详细展示了参数处理、加密逻辑和异常处理等关键环节,帮助开发者高效完成语音通知接口对接。

2601_94914653的博客 699

英文linux系统,部署GBK网站系统,在插件里出现乱码的问题

我们再给客户安装我们系统的时候,用delphi 开发的插件出现了乱码,经过分析: 1:服务器操作系统是 英文linux 2:数据库是oracle,网也内容没有乱码,不过插件里面读取出来的字段中文名称出现乱码 经过半天的研究,发现传输过来的XML里面内容是utf8,经过解析是可以解析出来,不过最后一些有很多少字符 因为时间因素,所以我们最后决定在字符串里面最后都加上了_pd...

小S资料屋 181

《碰到的一个编码问题》的回答:UTF-8的汉字字节!

埋伏: 1、UTF-8用几个字节表示一个汉字? 这各答案你可能了解,但也可能不了解,我敢打保票一半人会不清楚(包括特意查资料之前的我)。 了解这个对编程有什么影响? 以下我把对yoolywu的回答,转为帖子发表,以表重视。 [b]yollywu的问:[/b][quote]系统有两个子系统,一个是BS的,一个是delphi做的CS,中间的数据传输是通过XML进行传输的。在...

Qieqie 221

Delphi调用C#写的WebService时中文乱码的问题?

====================================================== 注:重要!用眼过度需要养眼,点此养眼! ====================================================== delphi调用c#写的webservice时中文乱码的问题? c#中webmethod代码如下: [webmethod] p

107

关于request中获取中文乱码的问题

前两天 遇到一个中文乱码的问题,搞了好久,又是加这个,又是加那个,就是不好用,无奈只能一点点找了,后来发现,原来在web.xml里面配置写错了。将encoding放在了拦截器的最下面。服了。。。说白了,当时配置框架的人没有想到这个问题。好吧。贴上这段utf-8转码的配置。 EncodingFilter org.springframework.web.filter.Characte

jalorchen 1013

UTF-8、iso-8859-1、GBK以及

  iSO8859-1,通常叫做Latin-1。Latin-1包括了书写所有西方欧洲语言不可缺少的附加字符。 而gb2312是标准中文字符集。 UTF-8 是 UNICODE 的一种变长字符编码,即 RFC 3629。简单的说——大字符集。可以解决多种语言文本显示问题,从而实现应用国际化和本地化。 对系统来讲,UTF-8 编码可以通过屏蔽位和移位操作快速读写,排序更加容易。UTF...

158
上一篇: 去掉非聚焦 stringGrid 的最后选中的 cell 颜色
下一篇: javascript 中的函数是覆盖的
laorer
博客等级 码龄24年 527粉丝 118原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值