为什么 TFileStream.write 会产生不正确的数据?德尔福 7
Why TFileStream.write produces incorrect data? Dephi 7
我试图创建一个 function/method 应该写入一个文件
一个 header 填充零
header := StringOfChar(char(0), 11*offsetSize);
但是当我检查创建的文件时,它具有以下值(十六进制):
C026A200160000000100000006000000264C656B63650000B2000000B04D45005C1EA200306CA20000000000
我预计输出文件应该包含
0000 0000 0000 0000 0000 0000
然后我也尝试用chr(1)
填充,结果类似:
C026A200160000000100000006000000264C656B63650000B2000000B04D45005C1EA200306CA20000000000
(看起来一样)。
当我在 Delphi 7 中调试时,我看到 header 填充了零:
#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
当我用 chr(1)
填充它时,它包含...
#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1
所以我的问题是,为什么会这样?输出文件包含错误数据我做错了什么?
unit Dictionary_io;
interface
uses
Classes, Windows, SysUtils, Dialogs;
const
offsetTableEntriesCount = 10;
type
TCountType = dword;
TOffsetType = dword;
TTextType = ANSIString;
const
testItemsCount = 1;
type
Dictionary = class
private
fsInput, fsOutput: TFileStream;
fileName: string;
msOffsets: TMemoryStream;
offsetSize: TOffsetType;
ofsTableEntries: TCountType;
lng: integer;
itemsCount: byte;
header: TTextType;
public
constructor Create;
procedure dicRewrite;
end;
implementation
constructor Dictionary.Create;
begin
offsetSize := sizeof(offsetSize);
end;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(char(0), 11*offsetSize);
try
fileName := 'A:\test.bin';
if FileExists(fileName) then
DeleteFile(fileName);
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.Write(header,Length(header));
finally
end;
finally
fsOutput.Free;
end;
end;
end.
您的数据没有正确写入文件的原因是您没有正确地将 header
传递给 Write()
。 Write()
将未类型化的 var
作为输入,并且您按原样将 header
变量传递给它,因此您传递 Write()
header
的内存地址本身。但是 string
包含指向存储在内存中其他位置的字符数据的指针。因此,为了将该数据写入您的文件,您需要取消引用 string
指针,以便您传入字符数据的内存地址。
此外,如果您不想检查 Write()
的 return 值是否有错误,您应该改用 WriteBuffer()
。
试试这个:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(#0, 11*offsetSize);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header[1], Length(header));
finally
fsOutput.Free;
end;
end;
或:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(#0, 11*offsetSize);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(PAnsiChar(header)^, Length(header));
finally
fsOutput.Free;
end;
end;
也就是说,您真的不应该对二进制数据使用 string
(特别是如果您计划将项目升级到 Delphi 2009+。您应该使用 record
或字节数组,例如:
private
header: array of Byte;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
SetLength(header, 11*offsetSize);
FillChar(header[0], Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header[0], Length(header));
finally
fsOutput.Free;
end;
end;
或:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
SetLength(header, 11*offsetSize);
FillChar(PByte(header)^, Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(PByte(header)^, Length(header));
finally
fsOutput.Free;
end;
end;
或:
private
header: array[0..(11*offsetSize)-1] of Byte;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
FillChar(header, Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header, SizeOf(header));
finally
fsOutput.Free;
end;
end;
我试图创建一个 function/method 应该写入一个文件 一个 header 填充零
header := StringOfChar(char(0), 11*offsetSize);
但是当我检查创建的文件时,它具有以下值(十六进制):
C026A200160000000100000006000000264C656B63650000B2000000B04D45005C1EA200306CA20000000000
我预计输出文件应该包含
0000 0000 0000 0000 0000 0000
然后我也尝试用chr(1)
填充,结果类似:
C026A200160000000100000006000000264C656B63650000B2000000B04D45005C1EA200306CA20000000000
(看起来一样)。
当我在 Delphi 7 中调试时,我看到 header 填充了零:
#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0#0
当我用 chr(1)
填充它时,它包含...
#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1#1
所以我的问题是,为什么会这样?输出文件包含错误数据我做错了什么?
unit Dictionary_io;
interface
uses
Classes, Windows, SysUtils, Dialogs;
const
offsetTableEntriesCount = 10;
type
TCountType = dword;
TOffsetType = dword;
TTextType = ANSIString;
const
testItemsCount = 1;
type
Dictionary = class
private
fsInput, fsOutput: TFileStream;
fileName: string;
msOffsets: TMemoryStream;
offsetSize: TOffsetType;
ofsTableEntries: TCountType;
lng: integer;
itemsCount: byte;
header: TTextType;
public
constructor Create;
procedure dicRewrite;
end;
implementation
constructor Dictionary.Create;
begin
offsetSize := sizeof(offsetSize);
end;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(char(0), 11*offsetSize);
try
fileName := 'A:\test.bin';
if FileExists(fileName) then
DeleteFile(fileName);
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.Write(header,Length(header));
finally
end;
finally
fsOutput.Free;
end;
end;
end.
您的数据没有正确写入文件的原因是您没有正确地将 header
传递给 Write()
。 Write()
将未类型化的 var
作为输入,并且您按原样将 header
变量传递给它,因此您传递 Write()
header
的内存地址本身。但是 string
包含指向存储在内存中其他位置的字符数据的指针。因此,为了将该数据写入您的文件,您需要取消引用 string
指针,以便您传入字符数据的内存地址。
此外,如果您不想检查 Write()
的 return 值是否有错误,您应该改用 WriteBuffer()
。
试试这个:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(#0, 11*offsetSize);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header[1], Length(header));
finally
fsOutput.Free;
end;
end;
或:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
header := StringOfChar(#0, 11*offsetSize);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(PAnsiChar(header)^, Length(header));
finally
fsOutput.Free;
end;
end;
也就是说,您真的不应该对二进制数据使用 string
(特别是如果您计划将项目升级到 Delphi 2009+。您应该使用 record
或字节数组,例如:
private
header: array of Byte;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
SetLength(header, 11*offsetSize);
FillChar(header[0], Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header[0], Length(header));
finally
fsOutput.Free;
end;
end;
或:
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
SetLength(header, 11*offsetSize);
FillChar(PByte(header)^, Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(PByte(header)^, Length(header));
finally
fsOutput.Free;
end;
end;
或:
private
header: array[0..(11*offsetSize)-1] of Byte;
procedure Dictionary.dicRewrite;
var
i: integer;
begin
itemsCount := 0;
FillChar(header, Length(header), #0);
fileName := 'A:\test.bin';
fsOutput := TFileStream.Create(fileName, fmCreate);
try
fsOutput.WriteBuffer(header, SizeOf(header));
finally
fsOutput.Free;
end;
end;