Delphi 将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),我

昨天我终于从Delphi7迁移到Delphi-XE5。我正在用Unicode重新编写整个应用程序,遇到了一些问题

让我们说,我有:

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。