- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用Delphi代码时遇到麻烦,这些代码使用TFileStream从文件读取数据块到动态数组。编写代码的最初目的是比较两个具有相同大小但可能具有不同日期和时间戳的文件的内容,以查看内容是否相同。通过将数据对从每个文件读取到单独的动态数组中,并将一个数组的每个字节与另一个数组的对应字节进行比较,即可完成此操作。
该代码多次调用TFileStream.Read。大约75次调用后,程序崩溃,并显示“内存不足”错误消息。
读取多大的数据块似乎无关紧要,似乎是导致错误消息的调用次数。
该代码是我编写的函数,只要程序遇到需要比较的两个文件(由于我不愿讨论的原因,它可能是四十个或五十个不同的文件对),该代码便在其他地方调用。无论是单个文件正在以小块读取,还是多个文件正在整体读取,都会发生“内存不足”错误。似乎是错误的决定因素是调用次数。
尽管我意识到可能有比下面显示的方法更优雅的文件比较方法,但我真正想知道的是,使用TFileStream和/或SetLength调用导致了内存问题。我尝试在每次调用后释放内存(如代码中所示),这似乎没有什么区别。
如果有人可以解释出什么问题了,我将不胜感激。
function Compare_file_contents(SPN,TPN : String; SourceFileSize : int64) : boolean;
var
SF : TFileStream; //First file of pair for comparison
TF : TFileStream; //Second file of pair
SourceArray : TBytes; // Buffer array to receive first file data
TargetArray : TBytes; //Buffer array to receive second file data
ArrayLength : int64; //Length of dynamic array
Position : int64; //Position within files to start each block of data read
TestPosition : int64; //Position within dynamic arrays to compare each byte
MaxArrayLength : integer; //Maximum size for the buffer arrays
LastRun : Boolean; //End first repeat loop
begin
{ The comparison has an arbitrary upper boundary of 100 MB to avoid slowing the
the overall program. The main files bigger than this will be *.pst files that
will most likely have new dates every time the program is run, so it will take
about the same time to copy the files as it does to read and compare them, and
it will have to be done every time.
The function terminates when it is confirmed that the files are not the same.
If the source file is bigger than 100 MB, it is simply assumed that they are
not identical, thus Result = False. Also, LongInt integers (=integers) have
a range of -2147483648..2147483647, so files bigger than 2 GB will have
overflowed to a negative number. Hence the check to see if the file size is
less than zero.
The outer repeat ... until loop terminates on LastRun, but LastRun should only
be set if SecondLastRun is True, because it will skip the final comparisons in
the inner repeat ... until loop otherwise. }
Result := True;
LastRun := False;
MaxArrayLength := 1024*1024;
if (SourceFileSize > 100*1024*1024) or (SourceFileSize < 0) then Result := False
else
begin
{ The comparison is done by using TFileStream to open and read the data from
the source and target files as bytes to dynamic arrays (TBytes). Then a repeat
loop is used to compare individual bytes until a difference is found or all
of the information has been compared. If a difference is found, Result is
set to False. }
if SourceFileSize > MaxArrayLength then ArrayLength := MaxArrayLength
else ArrayLength := SourceFileSize;
SF := TFileStream.Create(SPN,fmOpenRead);
TF := TFileStream.Create(TPN,fmOpenRead);
Position := 0;
SetLength(SourceArray,ArrayLength);
SetLength(TargetArray,ArrayLength);
try
SF.Read(SourceArray,ArrayLength);
TF.Read(TargetArray,ArrayLength);
Position := SF.Position;
finally
SF.Free;
TF.Free;
end;
repeat
TestPosition := 0;
repeat
if SourceArray[TestPosition] <> TargetArray[TestPosition] then
Result := False;
Inc(TestPosition);
until (Result = False) or (TestPosition = ArrayLength);
if SourceFileSize > Position then
begin
if SourceFileSize - Position - MaxArrayLength > 0 then
ArrayLength := MaxArrayLength
else ArrayLength := SourceFileSize - Position;
SF := TFileStream.Create(SPN,fmOpenRead);
TF := TFileStream.Create(TPN,fmOpenRead);
SF.Position := Position;
TF.Position := Position;
try
SF.Read(SourceArray,ArrayLength);
TF.Read(TargetArray,ArrayLength);
Position := SF.Position;
finally
SF.Free;
TF.Free;
end;
end else LastRun := True;
until (Result = False) or LastRun;
Finalize(SourceArray);
Finalize(TargetArray);
end;
end; { Compare_file_contents }
最佳答案
这个例程似乎要复杂得多。我没有尝试调试它,而是为您提供了比较流的例程。
function StreamsEqual(Stream1, Stream2: TStream): Boolean;
const
OneKB = 1024;
var
Buffer1, Buffer2: array [0..4*OneKB-1] of Byte;
SavePos1, SavePos2: Int64;
Count: Int64;
N: Integer;
begin
if Stream1.Size<>Stream2.Size then begin
Result := False;
exit;
end;
SavePos1 := Stream1.Position;
SavePos2 := Stream2.Position;
Try
Stream1.Position := 0;
Stream2.Position := 0;
Count := Stream1.Size;
while Count <> 0 do begin
N := Min(SizeOf(Buffer1), Count);
Stream1.ReadBuffer(Buffer1, N);
Stream2.ReadBuffer(Buffer2, N);
if not CompareMem(@Buffer1, @Buffer2, N) then begin
Result := False;
exit;
end;
dec(Count, N);
end;
Result := True;
Finally
Stream1.Position := SavePos1;
Stream2.Position := SavePos2;
End;
end;
关于delphi - delphi TFileStream“内存不足”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14799420/
我有这个代码单元:(我在 Win XP sp 3 上运行 Delphi 7)。 uses Windows, Messages, SysUtils, Variants, Classes, Graph
我需要扩展 TFileStream,以便它可以处理不是从 0 偏移量开始,而是从用户定义的偏移量开始的文件。我的意思是它必须将用户定义的偏移量解释为流开始。我的代码是: type TSuFileS
TFileStream 提供缓冲输出,这在大多数情况下都很好,但在某些情况下(特别是在调试期间)最好立即刷新缓冲区。问题是,除了调用 Free 之外,我不知道有什么方法可以做到这一点,这会适得其反。
我在使用Delphi代码时遇到麻烦,这些代码使用TFileStream从文件读取数据块到动态数组。编写代码的最初目的是比较两个具有相同大小但可能具有不同日期和时间戳的文件的内容,以查看内容是否相同。通
我在 Delphi 2006 中使用 TFileStream。当我使用超出范围的偏移量调用 TFileStream.Seek 时,我得到不同的返回值。当我寻找低于流开头的位置时,该函数返回 -1,如果
我们刚刚在 Delphi 2007 中遇到了 TFileStream.Seek 的一种特殊行为(实际上该方法是从 THandleStream 继承的): 您可以在没有错误的情况下查找文件末尾之外的内容
这是取自 https://forums.embarcadero.com/message.jspa?messageID=219481 的代码片段 if FileExists(dstFile) then
我搜索了又搜索,似乎找不到任何描述我想要在delphi代码中做什么的东西。这些解决方案有时很接近,但还不足以让我弄清楚。所以我在这里问.. 我有很多位图,我正在从屏幕截图中检索它们。我一直在做的是保存
我正在使用下面的代码写入现有文件,但内容会被附加。清空文件并覆盖它需要哪些 TFileStream 选项? procedure TUtilitiesForm.btnSaveClick(Sender:
为什么这段代码不起作用? 我正在编写一个应用程序,该应用程序能够保存和加载自己的文件,并且需要知道如何使用 FileStream 将对象流式传输到文件。 procedure TForm1.btnSav
这是我关于 SO 的第二个问题,我希望我的格式正确。 我在工作中发现 TFileStream 比 TMemoryStream 慢,我真的不知道为什么会这样。因此我决定做一些测试。 在我发现这种行为的应
我正在尝试使用 TFileStream 写入和读取非固定字符串。不过,我遇到了访问冲突 错误。这是我的代码: // Saving a file (...) count:=p.Tags.Coun
我使用 Delphi 和 TmongoWire。我想插入 TFileStream (picture, pdf)在 MongoDb 服务器上使用 TmongoWire。我的工作基于这个演示文件:Delp
我正在尝试写入更大的 block 以提高文件保存的速度。我大约有 9 个循环需要转换,但我不知道我做错了什么 fs := TFileStream.Create(Myfile, fmCreate); 此
例如,我有多种记录类型可以从文件中读取 PDescriptorBlockHeader = ^TDescriptorBlockHeader; TDescriptorBlockHeader = p
我正在尝试使用 TFilestream 写入网络共享(本地)。如果网络连接不中断,一切正常。 但是,如果我拔下网络电缆然后重新连接,由于访问限制,后续尝试打开文件流会失败。我什至无法删除资源管理器中的
我想在TFileStream上实现一个进度事件以进行读/写操作,以便在其上分配一个进度条。 我已经创建了 TFileStream 的 clild 类 (TProgressFileStream): un
如何使用某些行读取文件 TFileStream.我阅读了包含数百万个文件的行。所以我想在我只会使用的内存中播放 示例: Line 1: 00 00 00 00 00 00 00 00 Line 2:
我正在使用 TIdHttp 下载文件,然后使用 TIdHashMessageDigest5 检查其 MD5 哈希值,如下所示: http := TIdHttp.Create(); fs := TFil
这份QC报告说Delphi不支持文件共享模式FILE_SHARE_DELETE http://qc.embarcadero.com/wc/qcmain.aspx?d=45628 我需要将此模式与 TF
我是一名优秀的程序员,十分优秀!