我有一个类似下面的结构需要保存并从磁盘加载。
RSecStructure= packed record
Name : string[255]; {NEED UNICODE SUPPORT HERE}
ScreenName : string[255];
OrigFileName : string[255];
Prim : string[255];
ParentVersion : integer;
sTag1 : string[255];
sTag2 : string[255];
sTag3 : string[255];
sTag4 : string[255];
DateAdd : TDateTime;
DateModify : TDateTime;
end;
到目前为止,我已经使用过这样的东西来保存结构:
function
var F: FILE;
Hdr: RSecStructure;
begin
...
BlockWrite (F, Hdr, SizeOf(Hdr));
...
end
上面的代码在Delphi 7下工作。在D2009下,当我在短字符串和Unicode字符串之间进行分配时,我收到了很多警告信息。 到目前为止,我设法编写Delphi代码而没有任何编译器警告或提示,我想保持这样。 所以我需要一个优雅的方法是将磁盘保存(Unicode将很好但不是关键)到磁盘而不会收到警告。
答案 0 :(得分:8)
Delphi 2009中的字符串字段与以前的所有版本相同。 ShortString
不是Unicode类型。
所以你应该可以继续按原样使用该记录。
你说它在Delphi 7中有效。在Delphi 2009中它不吗?描述你遇到的问题。
你的意思是说你想要一个等长于ShortString
的固定长度的Unicode吗?没有一个,所以你不能有这样的记录,让它保持类似字符串的Unicode值,并将其直接保存到磁盘。
我不认为这是一个主要问题,因为你的磁盘格式无论如何都与你当前的格式不兼容:你的角色太大了。
您可以使用字符数组:
type
TSecStructure = packed record
Name : array[0..255] of UnicodeChar;
ScreenName : array[0..255] of UnicodeChar;
OrigFileName : array[0..255] of UnicodeChar;
Prim : array[0..255] of UnicodeChar;
ParentVersion : integer;
sTag1 : array[0..255] of UnicodeChar;
sTag2 : array[0..255] of UnicodeChar;
sTag3 : array[0..255] of UnicodeChar;
sTag4 : array[0..255] of UnicodeChar;
DateAdd : TDateTime;
DateModify : TDateTime;
end;
这不会像真正的字符串类型那样方便,但它可以用于大多数目的。
您还可以使用普通UnicodeString
类型:
type
TSecStructure = record
Name : UnicodeString;
ScreenName : UnicodeString;
OrigFileName : UnicodeString;
Prim : UnicodeString;
ParentVersion : integer;
sTag1 : UnicodeString;
sTag2 : UnicodeString;
sTag3 : UnicodeString;
sTag4 : UnicodeString;
DateAdd : TDateTime;
DateModify : TDateTime;
end;
您无法再将其直接保存到磁盘,但您不再限制为255个字符。您必须分别存储每个字符串字段。确保也存储字符串的长度,或者你不知道一个字符串的结束位置,以及下一个字符串的开始时间。
答案 1 :(得分:6)
或者,您可以声明可存储的短unicode字符串记录,并实现隐式'to string'和'from string'转换。
program TestShortUnicodeString;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TShortUnicodeString = record
private
Data: array [0..255] of char; //WARNING - NOT initialized to an empty string
public
class operator Implicit(const sus: TShortUnicodeString): string; inline;
class operator Implicit(const ws: string): TShortUnicodeString; inline;
end;
class operator TShortUnicodeString.Implicit(const sus: TShortUnicodeString): string;
begin
Result := StrPas(sus.Data);
end;
class operator TShortUnicodeString.Implicit(const ws: string): TShortUnicodeString;
begin
// too long strings are silently truncated
StrPLCopy(Result.Data, ws, Length(Result.Data)-1);
end;
type
TTestRec = record
ws1: TShortUnicodeString;
ws2: TShortUnicodeString;
end;
var
f : file;
test1: TTestRec;
test2: TTestRec;
begin
test1.ws1 := '6*9 =';
test1.ws2 := ' 42';
AssignFile(f, 'test.dat');
Rewrite(f, 1);
BlockWrite(f, test1, SizeOf(test1));
CloseFile(f);
AssignFile(f, 'test.dat');
Reset(f, 1);
Assert(FileSize(f) = SizeOf(test2));
BlockRead(f, test2, SizeOf(test2));
CloseFile(f);
Writeln(string(test2.ws1), string(test2.ws2));
Readln;
end.
[上述代码已发布到公共领域,不承担任何许可证义务。]
答案 2 :(得分:2)
您可以保留现有结构(字符串[255]),现有文件格式,甚至可以使用以下内容正确读取先前保存的非unicode数据:
在写数据之前:
...
record.Name:= UTF8EncodeToShortString(Name);
阅读数据后:
...
Name:= UTF8ToString(record.Name);