TFileStream 创建的文件缺少写入的数据
TFileStream created file missing data written to it
我编写了 client/server 代码,通过 Delphi 编写的 WebService 在系统之间来回移动文件。由于服务前面的网关的限制,我被迫将大文件拆分为多条消息。下面的代码在我的测试中经常有效。然而,有时,在最后一条数据上,它似乎没有进入结果文件。我有另一个版本的代码,我在其中的每一步都添加了大量日志记录,以验证 writeBuffer 调用前后 FileStream 中的当前位置,并获取中间文件的大小。该版本的代码似乎每次都能正常工作,这让我觉得我可能遇到了某种计时问题。我应该在每次写入或类似操作后对 Stream 进行刷新吗?
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
while processingGetFile do
begin
chunkID := StrToInt(responseObj.ValidationResults[0].ValidationResultId);
if chunkID = -3 then
begin
processingGetFile := false;
break;
end;
if chunkID = -2 then
begin
if responseObj.opsResponseobj.status then
begin
if responseObj.opsResponseObj.document <> 'NONEWFILE' then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
DecodedZipfile := DecodeString(responseObj.opsResponseobj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
FreeAndNil(Zipfile);
end;
result := true;
processingGetFile := false;
end
else
begin
//Log failure
end;
end
else if chunkID = -1 then
begin
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
result := true;
processingGetFile := false;
end
else // in the middle of receiving pieces of a big file. Save off what we have, ask for more.
begin
if chunkID = 1 then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
end;
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
GetFileInHeader.messageFlowSequence := chunkID;
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
end;
end;
function getFileSize(path: string): integer;
var
info : TWin32FileAttributeData;
begin
result := -1;
if not GetFileAttributesex(Pchar(path), GetFileExInfoStandard, @info) then
exit;
result := (info.nFileSizeLow or (info.nFileSizeHigh shl 32));
end;
您的问题似乎与是否需要执行更多操作才能写入文件有关:
Stream := TFileStream.Create(...);
Try
Stream.WriteBuffer(...);
Finally
Stream.Free;
End;
答案是否定的。没有必要冲洗任何东西。
您的问题可能与您使用的共享模式有关。您已完成 fmShareDenyNone
。这意味着可以打开多个具有写访问权限的文件句柄。这意味着您对文件写入竞赛持开放态度。
我编写了 client/server 代码,通过 Delphi 编写的 WebService 在系统之间来回移动文件。由于服务前面的网关的限制,我被迫将大文件拆分为多条消息。下面的代码在我的测试中经常有效。然而,有时,在最后一条数据上,它似乎没有进入结果文件。我有另一个版本的代码,我在其中的每一步都添加了大量日志记录,以验证 writeBuffer 调用前后 FileStream 中的当前位置,并获取中间文件的大小。该版本的代码似乎每次都能正常工作,这让我觉得我可能遇到了某种计时问题。我应该在每次写入或类似操作后对 Stream 进行刷新吗?
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
while processingGetFile do
begin
chunkID := StrToInt(responseObj.ValidationResults[0].ValidationResultId);
if chunkID = -3 then
begin
processingGetFile := false;
break;
end;
if chunkID = -2 then
begin
if responseObj.opsResponseobj.status then
begin
if responseObj.opsResponseObj.document <> 'NONEWFILE' then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
DecodedZipfile := DecodeString(responseObj.opsResponseobj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
FreeAndNil(Zipfile);
end;
result := true;
processingGetFile := false;
end
else
begin
//Log failure
end;
end
else if chunkID = -1 then
begin
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode);
result := true;
processingGetFile := false;
end
else // in the middle of receiving pieces of a big file. Save off what we have, ask for more.
begin
if chunkID = 1 then
begin
if FileExists2(DesintationFilePath) then
DeleteFile(DesintationFilePath);
Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate);
end;
Zipfile.Position := getFileSize(DesintationFilePath);
DecodedZipfile := DecodeString(responseObj.opsResponseObj.document);
Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile));
GetFileInHeader.messageFlowSequence := chunkID;
responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn);
end;
end;
function getFileSize(path: string): integer;
var
info : TWin32FileAttributeData;
begin
result := -1;
if not GetFileAttributesex(Pchar(path), GetFileExInfoStandard, @info) then
exit;
result := (info.nFileSizeLow or (info.nFileSizeHigh shl 32));
end;
您的问题似乎与是否需要执行更多操作才能写入文件有关:
Stream := TFileStream.Create(...);
Try
Stream.WriteBuffer(...);
Finally
Stream.Free;
End;
答案是否定的。没有必要冲洗任何东西。
您的问题可能与您使用的共享模式有关。您已完成 fmShareDenyNone
。这意味着可以打开多个具有写访问权限的文件句柄。这意味着您对文件写入竞赛持开放态度。