【问题标题】:TStringlist not loading Google Contacts fileTStringlist 未加载 Google 通讯录文件
【发布时间】:2016-02-03 11:36:44
【问题描述】:

我正在尝试使用 Stringlist 加载由 Google 通讯录生成的 CSV 文件。当我在像 Sublime Text 这样的文本编辑器中打开这个文件时,我可以正确地看到内容,有 75 行。这是来自 Google 通讯录文件的示例:

Name,Given Name,Additional Name,Family Name,Yomi Name,Given Name Yomi,Additional Name Yomi,Family Name Yomi,Name Prefix,Name Suffix,Initials,Nickname,Short Name,Maiden Name,Birthday,Gender,Location,Billing Information,Directory Server,Mileage,Occupation,Hobby,Sensitivity,Priority,Subject,Notes,Group Membership,Phone 1 - Type,Phone 1 - Value,Phone 2 - Type,Phone 2 - Value,Phone 3 - Type,Phone 3 - Value
H,H,,,,,,,,,,,,,   1-01-01,,,,,,,,,,,,* My Contacts ::: Importado 01/02/16,,,,,,
H - ?,H,-,?,,,,,,,,,,,   1-01-01,,,,,,,,,,,,* My Contacts ::: Importado 01/02/16,Mobile,031-863-64393,,,,
H - ?,H,-,?,,,,,,,,,,,,,,,,,,,,,,,* My Contacts ::: Importado 01/02/16,Mobile,031-986-364393,,,,

但是当我尝试使用 Stringlist 加载同一个文件时,这是我在 Stringlist.text 属性中看到的:

'ÿþN'#$D#$A

这是我的代码:

procedure Tform1.loadfile;
var sl : tstringlist;
begin
sl := tstringlist.create;
sl.loadfromfile('c:\google.csv');
showmessage('lines : '+inttostr(sl.count)+' / text : '+ sl.text);
end;

这是我得到的结果:

'1 / 'ÿþN'#$D#$A'

这里发生了什么?

谢谢

【问题讨论】:

  • 就可以了。但如果是我,我会在十六进制编辑器中加载文件并查看十六进制转储。你手头没有十六进制编辑器吗?你了解文本编码吗? Sublime 会告诉你编码是什么吗?
  • 不要再浪费时间了;请获取可以显示 HEX 格式文件的查看器。然后对该显示进行屏幕截图,然后仅在此处上传该图像的前几行。或者复制前几行显示的文本并将其放在上面的问题中。
  • UTF-8 编码文件的前三个字节将是 EF BB BF。在您第一次粘贴 stringlist.text: 'ÿþN'#$D#$A 时,开头有一个撇号。这也是文件的一部分吗?
  • 此信息是问题的关键。请在问题中包含它。带编辑。作为迄今为止有 50 多个问题的人,我觉得您现在应该知道这一点。
  • 请仔细阅读:embarcadero.com/images/dm/technical-papers/…。它将解释很多关于编码的内容。

标签: delphi delphi-2007 tstringlist


【解决方案1】:

根据您提供的十六进制转储,BOM 表明您的文件是使用 UTF-16LE 编码的。在我看来,您面前有几个选择:

  1. 切换到 Unicode 并使用 TnT Unicode 控件来处理此文件。
  2. 将文件作为字节数组读取。转换为 ANSI,然后继续使用 ANSI 编码的文本。显然,您将丢失任何无法由 ANSI 代码页编码的字符的信息。一种廉价的方法是将文件作为字节数组读取。将前两个字节(BOM)之后的内容复制到WideString 中。然后将 WideString 分配给 ANSI string
  3. 将您的程序移植到 Unicode 版本的 Delphi(任何高于 Delphi 2007 的版本)并在本机上使用 Unicode。

我相当怀疑您对文本编码不是很熟悉。如果你是那么我认为你将能够自己回答这个问题。这很好,但我敦促您花时间正确了解这个问题。如果你现在急于编码,在没有扎实的基础之前,你肯定会把它弄得一团糟。我们已经看到很多人犯了同样的错误。请不要添加到文本编码伤亡列表中。

【讨论】:

    【解决方案2】:

    感谢大卫的信息,我可以使用下面的函数来完成任务;因为Delphi 2007不支持unicode,所以需要第三方函数来做。

    procedure loadUnicodeFile( const filename: String; strings: TStringList);
    Procedure SwapWideChars( p: PWideChar );
    Begin
    While p^ <> #0000 Do Begin
    // p^ := Swap( p^ ); //<<< D3
    p^ := WideChar( Swap( Word(p^)));
    Inc( p );
    End; { While }
    End; { SwapWideChars }
    
    Var
    ms: TMemoryStream;
    wc: WideChar;
    pWc: PWideChar;
    Begin
    ms:= TMemoryStream.Create;
    try
    ms.LoadFromFile( filename );
    ms.Seek( 0, soFromend );
    wc := #0000;
    ms.Write( wc, sizeof(wc));
    
    pWC := ms.Memory;
    If pWc^ = #$FEFF Then // normal byte order mark
    Inc(pWc)
    Else If pWc^ = #$FFFE Then Begin // byte order is big-endian
    SwapWideChars( pWc );
    Inc( pWc );
    End { If }
    Else; // no byte order mark
    strings.Text := WideChartoString( pWc );
    finally
    ms.free;
    end;
    End;
    

    【讨论】:

      猜你喜欢
      • 2016-06-14
      • 1970-01-01
      • 2014-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多