十六进制文件修改时遇到的问题...(100分)

  • 主题发起人 主题发起人 zfh
  • 开始时间 开始时间
Z

zfh

Unregistered / Unconfirmed
GUEST, unregistred user!
最近写了一个专门进行十六进制文件查找替换的小程序,是用TMemoryStream实现的,不过在完善
功能的时候遇到了点问题,不知如何解决。
; ; 1、文件内容的查找和替换用TStream流实现了,可是我还想在修改文件后恢复原来的文件修改
日期,这个功能通常我们用FileSetDate函数来做,但这势必要求文件用FileOpen再打开一次,
不知道在流中能不能直接搞定?
; ; 2、如果不用流而是用FileOpen或Reset来打开文件的话,则要有一个足够大的缓冲区(buf)来读入文件内容,
这个缓冲区用固定大小的数组显然不合适,尝试用动态数组写了以下代码,但即使打开一个小文件也会非法操作,
不知错在哪里?
; ; var
; ; ; ;F: File of byte;
; ; ; ;Buf:array of byte; ; ; //这里如果不用动态数组就没事
; ; ; ;ReadBytes: integer;
; ; begin
; ; ; AssignFile(F,'bbb.bin');
; ; ; Reset(F);
; ; ; SetLength(Buf,filesize(F));
; ; ; try
; ; ; ; BlockRead(F,Buf,sizeof(buf),readbytes);
; ; ; finally
; ; ; ; CloseFile(F);
; ; ; end;
; ;end;
 
刚刚查了在线帮助,知道SetLength只能设255以内的长度,不过我以上所说的小文件也只有10几个字节,
应该不会出错的呀。
 
你完全可以设置一个固定大小的缓冲区,因为通常不会用 BlockRead 读入整个文件
而是一次读入一固定大小的小块

还是用 MapFile 算了,又快
 
不读入整个文件则不利于查找替换的简化,因为你要查找的的内容可能会被截断。
顺便说一下,用流也很快,只是无法解决我的第一个问题。
 
用固定长度缓冲区处理无类型文件处理又一个麻烦的地方,查找和替换时
需要考虑边界处理,用内存映射文件也存在这个问题,当文件太大时需要
处理。用流不存在这个问题,况且,他的Handle属性就是文件句柄,为什
么不直接用它呢?
 
是的,我所说的查找内容会被截断其实也就是边界处理问题。

另外,流有Handle属性吗?这个还真没注意,且容我测试一下,如通过则立即派分。谢谢。
 
很不幸,通不过。
 
为什么? 能说说么
 
错了错了,我原用的是TMemoryStream,所以没有文件句柄,看来得改用TFileStream了。我估计问题
应该解决了。
 
tseug:
出现信息是内存存取(非法地址),具体记不清了。
BTW,你那个小对话框是怎么弄出来的?
 
在线富翁里有个小闪电, 你点他就行了
你可以用下面的函数.
function FileSetDate(const FileName: string; Age: Integer): Integer;
不是这个
function FileSetDate(Handle: Integer; Age: Integer): Integer;
DELPHI里给重载了
 
可以用呀, 你看看吧

procedure TForm1.Button1Click(Sender: TObject);
var
;F : TFileStream ;
;H : Integer;
begin
;F := TFileStream.Create('C:/AUTOEXEC.BAT', fmOpenReadWrite);
;Memo1.Lines.LoadFromStream(F);
;H := F.Handle;
;FileSetDate(H, DateTimeToFileDate(Now));
;F.Free;
end;
 
1、SetLength(Buf,filesize(F)); 可以大于255的,只有shortstring才是255,其它可以大一点的
2、BlockRead(F,Pointer(Buf)^,filesize(F),readbytes);
; ;注意是filesize(F),不是sizeof(buf),buf实际是个指针,固定长度4
; ;另外用 Pointer(Buf)^ ,注意后面小小的 ^ 不能少
; ;(用c来理解delphi就好办很多了:)
 
谢谢二位。
tseug:
关于function FileSetDate(const FileName: string; Age: Integer): Integer;的问题,似乎行不通,
因为delphi和WinAPI都没有这样的声明,自己声明的话势必得自行写代码吧,不知你是怎样用的?
Pipi:
这个我是能理解的,只是不明白我原来的代码为什么把动态数组改为固定数组就没问题。

另外,如果改用文件流方式,仍然得申请缓冲区,这样似乎就与用fileopen来打开文件无异了。
我原用内存流的LoadFromFile方法来调入文件的,当然,这实际上系统并不比用文件流方式少做多少工作,
只不过申请动态缓冲区的工作由系统替我做了罢了。此外,这种方式(内存流)还有一个显而易见的缺点,就是
在操作的过程中不能阻止其它进程对文件的存取。

还想问一个相关的问题,用动态数组和GetMem分配内存哪一个更好些?
 
>只是不明白我原来的代码为什么把动态数组改为固定数组就没问题
我不是说了吗,Pointer(Buf)^ ,其实动态数组Buf不过是个Pointer变量,
固定数组是在stack已分配内存的一片存储区(用c来理解好一点)
 
我用的是Delphi6.0, 他自己声明的. 你可以查他的源程序
 
tseug:
我用的delphi5没有.
 
后退
顶部