Delphi 将unicode记录(数组)存储到文件中的最佳且简单的方法
昨天我终于从Delphi7迁移到Delphi-XE5。我正在用Unicode重新编写整个应用程序,遇到了一些问题 让我们说,我有:Delphi 将unicode记录(数组)存储到文件中的最佳且简单的方法,delphi,serialization,unicode,delphi-xe5,Delphi,Serialization,Unicode,Delphi Xe5,昨天我终于从Delphi7迁移到Delphi-XE5。我正在用Unicode重新编写整个应用程序,遇到了一些问题 让我们说,我有: TCountry = record Name: WideString; Extension: WideString; Region: WideString; end; 还有这个类的动态数组,我想在关闭时将其存储在一个文件中,然后在应用程序启动时加载。之前(在Delphi7中)我将其存储在INI文件中。但现在我想使用Unicode(UTF-16LE),我
TCountry = record
Name: WideString;
Extension: WideString;
Region: WideString;
end;
还有这个类的动态数组,我想在关闭时将其存储在一个文件中,然后在应用程序启动时加载。之前(在Delphi7中)我将其存储在INI文件中。但现在我想使用Unicode(UTF-16LE),我不想将其存储在INI文件中;也许我可以把它保存成二进制格式
我尝试了两种方法,只是想问一下,将带有Unicode字符串的动态数组存储到文件中的最佳方法是什么?试试下面的代码:
TYPE
TCountry = RECORD
Name : STRING;
Extension : STRING;
Region : STRING
END;
TCountryArr = ARRAY OF TCountry;
VAR
Countries : TCountryArr;
{$DEFINE UTF8 }
PROCEDURE SaveCountries(CONST FileName : STRING ; CONST ARR : TCountryArr);
VAR
S : TStream;
I : INTEGER;
PROCEDURE WriteString(S : TStream ; CONST STR : STRING);
VAR
LEN : INTEGER;
{$IFDEF UTF8 }
UTF8 : UTF8String;
{$ENDIF }
BEGIN
{$IFDEF UTF8 }
UTF8:=STR; LEN:=LENGTH(UTF8);
S.Write(LEN,SizeOf(INTEGER));
IF LEN>0 THEN S.Write(UTF8[LOW(UTF8)],LEN*SizeOf(AnsiChar))
{$ELSE }
LEN:=LENGTH(STR);
S.Write(LEN,SizeOf(INTEGER));
IF LEN>0 THEN S.Write(STR[LOW(STR)],LEN*SizeOf(CHAR))
{$ENDIF }
END;
BEGIN
S:=TFileStream.Create(FileName,fmCreate);
TRY
TRY
I:=LENGTH(ARR);
S.Write(I,SizeOf(INTEGER));
FOR I:=LOW(ARR) TO HIGH(ARR) DO WITH ARR[I] DO BEGIN
WriteString(S,Name);
WriteString(S,Extension);
WriteString(S,Region)
END
FINALLY
S.Free
END
EXCEPT
DeleteFile(FileName);
RAISE
END
END;
PROCEDURE LoadCountries(CONST FileName : STRING ; VAR ARR : TCountryArr);
VAR
S : TStream;
I : INTEGER;
PROCEDURE ReadString(S : TStream ; VAR STR : STRING);
VAR
LEN : INTEGER;
{$IFDEF UTF8 }
UTF8 : UTF8String;
{$ENDIF }
BEGIN
S.Read(LEN,SizeOf(INTEGER));
{$IFDEF UTF8 }
SetLength(UTF8,LEN);
IF LEN>0 THEN S.Read(UTF8[LOW(UTF8)],LEN*SizeOf(AnsiChar));
STR:=UTF8
{$ELSE }
SetLength(STR,LEN);
IF LEN>0 THEN S.Read(STR[LOW(STR)],LEN*SizeOf(CHAR))
{$ENDIF }
END;
BEGIN
S:=TFileStream.Create(FileName,fmOpenRead);
TRY
TRY
S.Read(I,SizeOf(INTEGER));
SetLength(ARR,I);
FOR I:=LOW(ARR) TO HIGH(ARR) DO WITH ARR[I] DO BEGIN
ReadString(S,Name);
ReadString(S,Extension);
ReadString(S,Region)
END
FINALLY
S.Free
END
EXCEPT
SetLength(ARR,0);
RAISE
END
END;
它将保存(并重新加载)一个TCountry数组到一个文件中。它可以在Unicode和非Unicode中工作(但文件不能在两者之间交换,即Unicode程序可以保存和重新加载Unicode文件,但非Unicode程序不能重新加载Unicode程序保存的文件)
编辑:如果您保留定义的UTF8符号,它将在二进制文件中使用UTF8编码。目前,它仅在启用Unicode的Delphi版本(2009或2010及以上)中可用,因为使用了UTF8String第一个问题。为什么要使用
WideString
?更广泛地说,您考虑过JSON或XML吗?前者可能更好,特别是如果您希望人们阅读文件。您仍然可以使用INI,只需使用TMemIniFile
而不是TMemIniFile
TMemIniFile
支持SyStudis.TunCode
,所以你可以保存Unicode数据作为UTF-8,例如,我正在考虑JSON,这不是问题。但是现在,我把它保存在UTF-8中作为XML,在加载之后我将它转换回Unicode。我将尝试更多的测试,这对我来说是最好的……在阅读了更多关于Delphi XE-5之后,我考虑使用字符串。(=UnicodeString)。@Legionar据我所知,没有XML库要求您执行手动Unicode转换。该库将接收字符串并对其进行内部编码(通常为UTF-8)反过来,库将解码XML文件中的字节,并递给Delphi字符串。这是UnoDeString 。不要考虑使用<代码> String < /C> >而不是<代码>广谱。请不要使用<代码> Untrys。除非您正在执行COM互操作。然后只在COM边界处执行。如果您正在启动,请使用。从长远来看,像JSON这样的东西会变得更容易。我一直在考虑JSON,这不会是一个问题。但现在,我将它保存为UTF-8中的XML,加载后我将它转换回Unicode。我将尝试更多的测试,这对我来说是最好的…@HEARTWARE如果使用UTF-8会更好吗?@Davidhefferan当然-这里事实上,即使在旧的Delphi版本中也可以编写UTF8。