TStringlist未加载Google通讯录文件

时间:2016-02-03 11:36:45

标签: delphi delphi-2007 tstringlist

我正在尝试使用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'

这里发生了什么?

由于

2 个答案:

答案 0 :(得分:2)

根据您提供的十六进制转储,BOM表示您的文件使用UTF-16LE进行编码。正如我所见,你面前有几个选择:

  1. 切换到Unicode并使用TnT Unicode控件来处理此文件。
  2. 将文件作为字节数组读取。转换为ANSI,然后继续使用ANSI编码的文本。显然,您将丢失任何字符的信息,而不是ANSI代码页无法编码的信息。一种廉价的方法是将文件作为字节数组读取。将前两个字节(BOM)后的内容复制到WideString。然后将WideString分配给ANSI string
  3. 将您的程序移植到Unicode版本的Delphi(比Delphi 2007更晚)并使用Unicode本地工作。
  4. 我宁愿怀疑你对文本编码不是很熟悉。如果你那时我认为你本可以自己回答这个问题。这很好,但我恳请你花时间正确地了解这个问题。如果您现在急于编码,在接地之前,您肯定会弄得一团糟。我们已经看到很多人犯了同样的错误。请不要添加到编码伤亡人员的文本列表中。

答案 1 :(得分:-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;