将unicode记录(数组)存储到文件中的最佳和简单方法

时间:2014-03-04 18:07:38

标签: delphi serialization unicode delphi-xe5

昨天我终于从Delphi 7转到了Delphi-XE5。我正在将整个应用程序重写为Unicode并遇到一些麻烦。

Lets说,我有:

TCountry = record
  Name: WideString;
  Extension: WideString;
  Region: WideString;
end;

并拥有此类的动态数组,我想将其存储在close文件中,然后在启动应用程序时加载。之前(在Delphi 7中)我将它存储在INI文件中。但现在我想使用Unicode(UTF-16LE),我不想将它存储在INI文件中;也许我可以用一些二进制格式保存它。

我尝试了几种方法,只是想问一下,将带有Unicode字符串的动态数组存储到文件中的最佳方法(方法)是什么?

1 个答案:

答案 0 :(得分:1)

试试这段代码:

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编码。由于使用了UTF8String,它只能在支持Unicode的Delphi版本(2009年或2010年及以上版本)中使用