D
dreamones
Unregistered / Unconfirmed
GUEST, unregistred user!
从网上找到这么一段代码,可以将打开的文件以16进制的方式打开.
但发现有一个缺陷,就是这段代码是把文件转化为16进制串,然后载入内存,再一次性显示出来,所以,在打开比较大文件的时候,内存消耗会很大.不小心还会当机!
所以,我想这样修改:如果打开的文件大于某个数值(比如1M),那么就让它分成N段,每一段大小1M,显示完1M的数据之后再接着转换下一段数据,再显示出来......
无奈小弟比较菜,在这段代码改了半天,没改出个所以然来,所以希望各位帮忙修改一下,如果分数不够,我可以再加!谢谢啦
unit main;
{ Recently I needed a hex viewer with copy-to-clipboard facility,
which gave me an excuse to use the rich edit TConversion class.
The code is nothing flash, but as there's very little documentation
of the class I figured others might appreciate it.
This was meant for use with 64K-256K EPROM images, so don't expect
blazing performance with multi-megabyte files!
G.Walker, November 1996 Delphi 2.0 freeware
gw@enternet.com.au Use at own risk, etc
Version 1.4
}
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs,
Menus, StdCtrls, ComCtrls;
type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
MenuFile: TMenuItem;
MenuOpen: TMenuItem;
MenuSaveAs: TMenuItem;
N1: TMenuItem;
MenuExit: TMenuItem;
OpenDlg: TOpenDialog;
SaveDlg: TSaveDialog;
Rich: TRichEdit;
StatusBar: TStatusBar;
MenuPopup: TPopupMenu;
MenuSelectAll: TMenuItem;
MenuCopy: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure MenuOpenClick(Sender: TObject);
procedure MenuSaveAsClick(Sender: TObject);
procedure MenuExitClick(Sender: TObject);
procedure MenuPopupPopup(Sender: TObject);
procedure MenuSelectAllClick(Sender: TObject);
procedure MenuCopyClick(Sender: TObject);
private
procedure Progress(Address:LongInt);
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
type
THexConversion = class(TConversion)
public
function ConvertReadStream(Stream:TStream; BufferChar;
BufSize:integer): integer; override;
end;
// This implements a callback procedure used by TRichEdit when loading
// a file. Gets called repeatedly until stream is empty.
//
function THexConversion.ConvertReadStream(Stream:TStream; BufferChar;
BufSize:integer): integer;
var s:string;
buf:array[1..16] of char;
i,n:integer;
begin
Result := 0;
if BufSize <= 82 then Exit;
s := Format(';%.5x ',[Stream.Position]);
n := Stream.Read(buf,16);
if n = 0 then Exit;
for i := 1 to n do
begin
AppendStr(s,IntToHex(ord(buf),2)+' ');
if i mod 4 = 0 then AppendStr(s,' ');
end;
AppendStr(s,StringOfChar(' ',62-length(s)));
for i := 1 to n do
begin
if (buf < #32) or (buf > #126) then
buf := '.';
AppendStr(s,buf);
end;
AppendStr(s,#13#10);
StrPCopy(Buffer,s);
Result := length(s);
if Stream.Position and $FFF = 0 then MainForm.Progress(Stream.Position);
end;
procedure TMainForm.Progress(Address:LongInt);
begin
StatusBar.SimpleText := 'Reading... $'+IntToHex(Address,5);
StatusBar.Update;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
Rich.RegisterConversionFormat('bin',THexConversion);
Rich.RegisterConversionFormat('obj',THexConversion);
Rich.RegisterConversionFormat('exe',THexConversion);
end;
procedure TMainForm.MenuOpenClick(Sender: TObject);
var fname:string;
begin
if OpenDlg.Execute then
begin
try
Screen.Cursor := crHourglass;
fname := ExtractFileName(OpenDlg.Filename);
StatusBar.SimpleText := 'Reading...';
Rich.Lines.Clear;
Application.ProcessMessages;
try
Rich.Lines.LoadFromFile(OpenDlg.Filename);
StatusBar.SimpleText := fname;
except on E:EFOpenError do
begin
StatusBar.SimpleText := '';
MessageDlg(Format('Can''t open file %s.',[fname]),mtError,[mbOk],0);
end;
end;
finally
Screen.Cursor := crDefault;
end;
end;
end;
procedure TMainForm.MenuSaveAsClick(Sender: TObject);
begin
SaveDlg.Filename := ChangeFileExt(OpenDlg.FileName,'.txt');
if SaveDlg.Execute then
Rich.Lines.SaveToFile(SaveDlg.FileName);
end;
procedure TMainForm.MenuExitClick(Sender: TObject);
begin
Close;
end;
procedure TMainForm.MenuPopupPopup(Sender: TObject);
var SelStart,SelEnd:LongInt;
begin
Rich.Perform(EM_GETSEL,WPARAM(@SelStart),WPARAM(@SelEnd));
MenuCopy.Enabled := SelStart <> SelEnd;
end;
procedure TMainForm.MenuSelectAllClick(Sender: TObject);
begin
Rich.Perform(EM_SETSEL,0,-1);
end;
procedure TMainForm.MenuCopyClick(Sender: TObject);
begin
Rich.Perform(WM_COPY,0,0);
end;
end.
哦,对了.这个RegisterConversionFormat是什么东东,哪位兄弟能讲讲它的用途和功能.谢谢@!
但发现有一个缺陷,就是这段代码是把文件转化为16进制串,然后载入内存,再一次性显示出来,所以,在打开比较大文件的时候,内存消耗会很大.不小心还会当机!
所以,我想这样修改:如果打开的文件大于某个数值(比如1M),那么就让它分成N段,每一段大小1M,显示完1M的数据之后再接着转换下一段数据,再显示出来......
无奈小弟比较菜,在这段代码改了半天,没改出个所以然来,所以希望各位帮忙修改一下,如果分数不够,我可以再加!谢谢啦
unit main;
{ Recently I needed a hex viewer with copy-to-clipboard facility,
which gave me an excuse to use the rich edit TConversion class.
The code is nothing flash, but as there's very little documentation
of the class I figured others might appreciate it.
This was meant for use with 64K-256K EPROM images, so don't expect
blazing performance with multi-megabyte files!
G.Walker, November 1996 Delphi 2.0 freeware
gw@enternet.com.au Use at own risk, etc
Version 1.4
}
interface
uses
Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs,
Menus, StdCtrls, ComCtrls;
type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
MenuFile: TMenuItem;
MenuOpen: TMenuItem;
MenuSaveAs: TMenuItem;
N1: TMenuItem;
MenuExit: TMenuItem;
OpenDlg: TOpenDialog;
SaveDlg: TSaveDialog;
Rich: TRichEdit;
StatusBar: TStatusBar;
MenuPopup: TPopupMenu;
MenuSelectAll: TMenuItem;
MenuCopy: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure MenuOpenClick(Sender: TObject);
procedure MenuSaveAsClick(Sender: TObject);
procedure MenuExitClick(Sender: TObject);
procedure MenuPopupPopup(Sender: TObject);
procedure MenuSelectAllClick(Sender: TObject);
procedure MenuCopyClick(Sender: TObject);
private
procedure Progress(Address:LongInt);
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
type
THexConversion = class(TConversion)
public
function ConvertReadStream(Stream:TStream; BufferChar;
BufSize:integer): integer; override;
end;
// This implements a callback procedure used by TRichEdit when loading
// a file. Gets called repeatedly until stream is empty.
//
function THexConversion.ConvertReadStream(Stream:TStream; BufferChar;
BufSize:integer): integer;
var s:string;
buf:array[1..16] of char;
i,n:integer;
begin
Result := 0;
if BufSize <= 82 then Exit;
s := Format(';%.5x ',[Stream.Position]);
n := Stream.Read(buf,16);
if n = 0 then Exit;
for i := 1 to n do
begin
AppendStr(s,IntToHex(ord(buf),2)+' ');
if i mod 4 = 0 then AppendStr(s,' ');
end;
AppendStr(s,StringOfChar(' ',62-length(s)));
for i := 1 to n do
begin
if (buf < #32) or (buf > #126) then
buf := '.';
AppendStr(s,buf);
end;
AppendStr(s,#13#10);
StrPCopy(Buffer,s);
Result := length(s);
if Stream.Position and $FFF = 0 then MainForm.Progress(Stream.Position);
end;
procedure TMainForm.Progress(Address:LongInt);
begin
StatusBar.SimpleText := 'Reading... $'+IntToHex(Address,5);
StatusBar.Update;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
Rich.RegisterConversionFormat('bin',THexConversion);
Rich.RegisterConversionFormat('obj',THexConversion);
Rich.RegisterConversionFormat('exe',THexConversion);
end;
procedure TMainForm.MenuOpenClick(Sender: TObject);
var fname:string;
begin
if OpenDlg.Execute then
begin
try
Screen.Cursor := crHourglass;
fname := ExtractFileName(OpenDlg.Filename);
StatusBar.SimpleText := 'Reading...';
Rich.Lines.Clear;
Application.ProcessMessages;
try
Rich.Lines.LoadFromFile(OpenDlg.Filename);
StatusBar.SimpleText := fname;
except on E:EFOpenError do
begin
StatusBar.SimpleText := '';
MessageDlg(Format('Can''t open file %s.',[fname]),mtError,[mbOk],0);
end;
end;
finally
Screen.Cursor := crDefault;
end;
end;
end;
procedure TMainForm.MenuSaveAsClick(Sender: TObject);
begin
SaveDlg.Filename := ChangeFileExt(OpenDlg.FileName,'.txt');
if SaveDlg.Execute then
Rich.Lines.SaveToFile(SaveDlg.FileName);
end;
procedure TMainForm.MenuExitClick(Sender: TObject);
begin
Close;
end;
procedure TMainForm.MenuPopupPopup(Sender: TObject);
var SelStart,SelEnd:LongInt;
begin
Rich.Perform(EM_GETSEL,WPARAM(@SelStart),WPARAM(@SelEnd));
MenuCopy.Enabled := SelStart <> SelEnd;
end;
procedure TMainForm.MenuSelectAllClick(Sender: TObject);
begin
Rich.Perform(EM_SETSEL,0,-1);
end;
procedure TMainForm.MenuCopyClick(Sender: TObject);
begin
Rich.Perform(WM_COPY,0,0);
end;
end.
哦,对了.这个RegisterConversionFormat是什么东东,哪位兄弟能讲讲它的用途和功能.谢谢@!