- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想在TFileStream
上实现一个进度事件以进行读/写操作,以便在其上分配一个进度条。
我已经创建了 TFileStream
的 clild 类 (TProgressFileStream
):
unit ProgressFileStream;
interface
uses
System.SysUtils,
System.Classes;
type
TProgressFileStreamOnProgress = procedure(Sender: TObject; Processed: Int64; Size: Int64; ContentLength : Int64; TimeStart : cardinal) of object;
TProgressFileStream = class(TFileStream)
private
FOnProgress: TProgressFileStreamOnProgress;
FProcessed: Int64;
FContentLength: Int64;
FTimeStart: cardinal;
FBytesDiff: cardinal;
FSize: Int64;
procedure Init;
procedure DoProgress(const AProcessed : Longint);
protected
procedure SetSize(NewSize: Longint); overload; override;
public
constructor Create(const AFileName: string; Mode: Word); overload;
constructor Create(const AFileName: string; Mode: Word; Rights: Cardinal); overload;
function Read(var Buffer; Count: Longint): Longint; overload; override;
function Write(const Buffer; Count: Longint): Longint; overload; override;
function Read(Buffer: TBytes; Offset, Count: Longint): Longint; overload; override;
function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; overload; override;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override;
property OnProgress: TProgressFileStreamOnProgress read FOnProgress write FOnProgress;
property ContentLength: Int64 read FContentLength write FContentLength;
property TimeStart: cardinal read FTimeStart write FTimeStart;
property BytesDiff: cardinal read FBytesDiff write FBytesDiff;
end;
implementation
uses
Winapi.Windows;
{ TProgressFileStream }
constructor TProgressFileStream.Create(const AFileName: string; Mode: Word);
begin
inherited Create(AFileName, Mode);
Init;
end;
constructor TProgressFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
begin
inherited Create(AFileName, Mode, Rights);
Init;
end;
function TProgressFileStream.Read(var Buffer; Count: Longint): Longint;
begin
Result := inherited Read(Buffer, Count);
DoProgress(Result);
end;
function TProgressFileStream.Write(const Buffer; Count: Longint): Longint;
begin
Result := inherited Write(Buffer, Count);
DoProgress(Result);
end;
function TProgressFileStream.Read(Buffer: TBytes; Offset, Count: Longint): Longint;
begin
Result := inherited Read(Buffer, Offset, Count);
DoProgress(Result);
end;
function TProgressFileStream.Write(const Buffer: TBytes; Offset, Count: Longint): Longint;
begin
Result := inherited Write(Buffer, Offset, Count);
DoProgress(Result);
end;
function TProgressFileStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
begin
Result := inherited Seek(Offset, Origin);
if Origin <> soCurrent then
FProcessed := Result;
end;
procedure TProgressFileStream.SetSize(NewSize: Longint);
begin
inherited SetSize(NewSize);
FSize := NewSize;
end;
procedure TProgressFileStream.Init;
const
BYTES_DIFF = 1024*100;
begin
FOnProgress := nil;
FProcessed := 0;
FContentLength := 0;
FTimeStart := GetTickCount;
FBytesDiff := BYTES_DIFF;
FSize := Size;
end;
procedure TProgressFileStream.DoProgress(const AProcessed : Longint);
var
aCurrentProcessed : Longint;
begin
if not(Assigned(FOnProgress)) then Exit;
aCurrentProcessed := FProcessed;
Inc(FProcessed, AProcessed);
if FContentLength = 0 then
FContentLength := FSize;
if (FProcessed = FSize) or (FBytesDiff = 0) or (aCurrentProcessed - FBytesDiff < FProcessed) then
FOnProgress(Self, FProcessed, FSize, FContentLength, FTimeStart);
end;
end.
基本用法是
procedure TWinMain.ProgressFileStreamOnProgressUpload(Sender: TObject; Processed: Int64; Size: Int64; ContentLength : Int64; TimeStart : cardinal);
begin
if Processed > 0 then
ProgressBar.Position := Ceil((Processed/ContentLength)*100);
end;
procedure TWinMain.BtnTestClick(Sender: TObject);
const
ChunkSize = $F000;
var
aBytes: TBytes;
aBytesRead : integer;
aProgressFileStream : TProgressFileStream;
begin
aProgressFileStream := TProgressFileStream.Create('MyFile.zip', fmOpenRead or fmShareDenyWrite);
SetLength(aBytes, ChunkSize);
try
aProgressFileStream.OnProgress := ProgressFileStreamOnProgressUpload;
aProgressFileStream.Seek(0, soFromBeginning);
repeat
aBytesRead := aProgressFileStream.Read(aBytes, ChunkSize);
until (aBytesRead = 0);
finally
aProgressFileStream.Free;
end;
end;
问题出在调用事件的方法中,我想每个 FBytesDiff
调用事件(默认每 100 KBytes):
procedure TProgressFileStream.DoProgress(const AProcessed : Longint);
var
aCurrentProcessed : Longint;
begin
if not(Assigned(FOnProgress)) then Exit;
aCurrentProcessed := FProcessed;
Inc(FProcessed, AProcessed);
if FContentLength = 0 then
FContentLength := Size;
if (FProcessed = Size) or (FBytesDiff = 0) or (FProcessed - aCurrentProcessed > FBytesDiff) then
FOnProgress(Self, FProcessed, Size, FContentLength, FTimeStart);
end;
但该事件似乎在每个 ChunkSize(61440 字节 - 60 KB)上触发...
我想添加此控件,以免因过多的事件调用而浪费流读/写的性能。
最佳答案
FProcessed - aCurrentProcessed 将返回 block 大小。我认为你应该创建一个变量来存储读取 block FReadSize
,将其初始化为0。如果读取的大小大于FBytesDiff,则用读取的字节数递增该变量,然后从FReadSize中减去FBytesDiff。
procedure TProgressFileStream.DoProgress(const AProcessed : Longint);
var
aCurrentProcessed : Longint;
begin
if not(Assigned(FOnProgress)) then Exit;
aCurrentProcessed := FProcessed;
Inc(FProcessed, AProcessed);
Inc(FReadSize, AProcessed);
if FContentLength = 0 then
FContentLength := Size;
if (FProcessed = Size) or (FBytesDiff = 0) or (FReadSize >= FBytesDiff) then
begin
FOnProgress(Self, FProcessed, Size, FContentLength, FTimeStart);
FReadSize := FReadSize - FBytesDiff;
end;
end;
关于Delphi:TFileStream 读/写进度(不浪费性能),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43638115/
我有这个代码单元:(我在 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
我是一名优秀的程序员,十分优秀!