1

可以在 Delphi 6 中将 XML 转换为 UTF-8 编码吗?
目前这就是我正在做的事情:

  • 用 AnsiString 填充 TXMLDocument
  • 最后通过使用将数据转换为 UTF-8WideStringVariable = AnsiToUtf8(Doc.XML.Text);
  • WideStringVariable在文件开头使用TFileStream和添加将值保存到文件中BOM for UTF8

代码:

Procedure SaveAsUTF8( const Name:String; Data: TStrings );

const
  cUTF8 = $BFBBEF;
var
  W_TXT: WideString;
  fs: TFileStream;
  wBOM: Integer;
begin
  if TRIM(Data.Text) <> '' then begin    
    W_TXT:= AnsiToUTF8(Data.Text);
    fs:= Tfilestream.create( Name, fmCreate );
    try
      wBOM := cUTF8;
      fs.WriteBUffer( wBOM, sizeof(wBOM)-1);
      fs.WriteBuffer( W_TXT[1], Length(W_TXT)*Sizeof( W_TXT[1] ));
    finally
      fs.free
    end;
  end;
end;

如果我在 Notepad++ 或其他检测编码的编辑器中打开文件,它会显示带有 BOM 的 UTF-8。但是,它似乎没有正确编码文本。

出了什么问题,我该如何解决?

更新:XML 属性:

XMLDoc.Version := '1.0';
XMLDoc.Encoding := 'UTF-8';
XMLDoc.StandAlone := 'yes';
4

4 回答 4

3

您可以在变量上使用标准SaveToFile方法保存文件:http: //docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/XMLDoc_TXMLDocument_SaveToFile.htmlTXMLDocument

无论文件是否为 UTF8,您都必须使用本地工具(如前面提到的 Notepad++ 或 Hex Editor 或其他任何工具)进行检查。


如果你坚持使用中间字符串和文件流,你应该使用正确的变量。AnsiToUTF8返回UTF8String类型,这就是要使用的。编译 `WideStringVar := AnsiStringSource' 会发出编译器警告和

这是一个适当的警告。谷歌搜索“Delphi WideString” - 或阅读有关主题的 Delphi 手册 - 表明WideStringakaMicrosoft OLE BSTR以 UTF-16 格式保存数据。http://delphi.about.com/od/beginners/l/aa071800a.htm 因此赋值UTF16 string <= 8-bit source必然会转换数据,因此转储WideString数据不能被UTF-8定义为转储文本WideString

Procedure SaveAsUTF8( const Name:String; Data: TStrings );
const
  cUTF8: array [1..3] of byte = ($EF,$BB,$BF)
var
  W_TXT: UTF8String;
  fs: TFileStream;
  Trimmed: AnsiString;
begin
  Trimmed := TRIM(Data.Text);
  if Trimmed <> '' then begin    
    W_TXT:= AnsiToUTF8(Trimmed);
    fs:= TFileStream.Create( Name, fmCreate );
    try
      fs.WriteBuffer( cUTF8[1], sizeof(cUTF8) );
      fs.WriteBuffer( W_TXT[1], Length(W_TXT)*Sizeof( W_TXT[1] ));
    finally
      fs.free
    end;
  end;
end;

顺便说一句,如果源数据为空,您的这段代码甚至不会创建空文件。它看起来相当可疑,尽管由你来决定这是否是一个错误或者不是你程序的其余部分。


将接收到的文件或流正确“上传”到网络是另一个问题(将作为一个单独的问题放在像 SO 这样的问答网站上),与测试与 HTTP 的一致性有关。作为前言,您可以在 Delphi 中的 Internet Direct 组件发出 POST 请求后阅读 WWW 服务器报告错误的一些提示

于 2013-07-18T13:27:15.283 回答
2

为了在文档中拥有正确的编码,您应该使用 XML 文档中的 Encoding 属性来设置它,如下所示:

myXMLDocument.Encoding := 'UTF-8';

我希望这有帮助。

于 2013-07-18T12:23:30.297 回答
2

您只需要调用SaveToFile文档的方法:

XMLDoc.SaveToFile(FileName);

由于您已经指定了编码,因此组件将使用该编码。

这不包括 BOM,但这通常是您想要的 XML 文件。文件的内容将指定编码。


至于您的SaveAsUTF8方法,它不是必需的,但很容易修复。这可能对你有启发。

问题是您在分配给WideString变量时正在转换为 UTF-16。您应该改为将 UTF-8 文本放入AnsiString变量中。更改您命名的变量的类型W_TXTAnsiString足够了。

该函数可能如下所示:

Procedure SaveAsUTF8(const Name: string; Data: TStrings);
const    
  UTF8BOM: array [0..2] of AnsiChar = #$EF#$BB#$BF;
var
  utf8: AnsiString;
  fs: TFileStream;
begin
  utf8 := AnsiToUTF8(Data.Text);
  fs:= Tfilestream.create(Name, fmCreate);
  try
    fs.WriteBuffer(UTF8BOM, SizeOf(UTF8BOM));
    fs.WriteBuffer(Pointer(utf8)^, Length(utf8));
  finally
    fs.free;
  end;
end;
于 2013-07-18T13:04:21.093 回答
1

另一种解决方案:

procedure SaveAsUTF8(const Name: string; Data: TStrings);
var
  fs: TFileStream;
  vStreamWriter: TStreamWriter;
begin
  fs := TFileStream.Create(Name, fmCreate);
  try
    vStreamWriter := TStreamWriter.Create(fs, TEncoding.UTF8);
    try
      vStreamWriter.Write(Data.Text);
    finally
      vStreamWriter.Free;
    end;
  finally
    fs.free;
  end;
end;
于 2016-09-14T17:38:18.110 回答