我维护一个Delphi程序,它使用类型化的二进制文件作为其本机文件格式。从Turbo Delphi升级到Delphi 2010后,存储的记录类型中的所有字符开始以2个字节而不是1个字节存储。
存储的数据类型为char
和array[1..5] of char
。
之前,该文件的一部分看起来像:
4C 20 20 20 4E 4E 4E 4E
现在看起来像:
4C 00 20 00 20 00 20 00 4E 00 4E 00 4E 00 4E 00
首先,为什么会在第一时间发生这种情况?
其次,我怎样才能读取我的文件,请记住现在宇宙中存在旧文件和新文件?
我会在午餐后痴迷地监听这个问题。请随意在评论中询问更多信息。
答案 0 :(得分:11)
在Delphi 2009中将默认字符串类型从AnsiString更改为UnicodeString时发生这种情况。听起来就像是在向文件写入字符串。在记录中将它们重新声明为AnsiString
,它应该可以正常工作。
同样适用于char
。原始的char是一个AnsiChar,每个字符一个字节。现在默认的char是一个WideChar,它是一个UTF-16字符,每个字符2个字节。将您的char数组重新声明为AnsiChar
的数组,然后您将恢复旧的文件样式。
至于知道这两种风格都存在,这是一团糟。除非升级Delphi版本时文件中的版本号已被更改,否则我认为你唯一能做的就是在字符数据中扫描00
个字节,然后用{ {1}}或记录的AnsiChar
版本,具体取决于是否找到记录。
答案 1 :(得分:0)
在您的代码中,将字符串类型声明更改为AnsiString,并将char类型声明更改为AnsiChar。它将使用与以前版本的Delphi相同的编码。 AnsiString / AnsiChar类型也适用于以前版本的Delphi。 但是没有全局编译器切换。 然后将此AnsiString / AnsiChar转换为unicode字符串。
这是两个例子,做同样的事情,一个使用AnsiChar数组,一个直接读取AnsiString内容。两者都返回一个通用的Unicode字符串:
function Read5(S: Stream): string;
var chars: array[1..5] of AnsiChar;
tmp: AnsiString;
i: integer;
begin
S.Read(chars,5);
for i := 1 to 5 do
tmp := tmp+chars[i];
result := string(tmp);
end;
function Read5(S: Stream): string;
var tmp: AnsiString;
begin
SetLength(tmp,5);
S.Read(tmp[1],5);
result := string(tmp);
end;
您可以在所有程序中使用AnsiChars,没有任何问题。
但如果您的AnsiChars用于字符串函数(如pos或copy),则可能会遇到一些问题。
始终密切关注Delphi 2010编译器警告,并尝试通过使它们显式化来避免任何隐式的ansi-unicode转换。