请问如何提高大二进制文件的读取速度?(100分)

  • 主题发起人 主题发起人 moutocean
  • 开始时间 开始时间
M

moutocean

Unregistered / Unconfirmed
GUEST, unregistred user!
请问如何提高大二进制文件的读取速度?请给出具体例程,
多谢!
 
使用文件映像FileMap,具体我也不懂
 
具体程序我从来都懒得写。
多大的文件?怎样的访问方法(从头读到尾还是跳跳跳)?
看一看 win api : CreateFile 的使用方法,其中包括了操作系统的缓冲策略。
另外,一次读出文件至少 1MB(假如是顺序访问)。
 
var
f1:file;
a1:array of [1..1024] of byte;
begin
assignfile(f1,'filename');filemode:=0;
reset(f1,1024);
while not eof(f1) do
read(f1,a1);
end;
数组越大,读取速度越快
 
一、用WINAPI直接操作(繁但快)
二、缓冲区尽量大
 
诸位大侠什么是文件映射?
 
小块的读,省内存
 
在delphi中的代码如何写?
 
使用文件映射,速度是最快的。
注意检查错误,随手写的,没测试过。
var
h:Integer;
p:Pointer;
........
fs:=TFileStream.Create('c:/abc.bin',fmOpenRead);
try
h := CreateFileMapping(fs.Handle, nil, PAGE_READWRITE,0, 0, 'MyFileMappingObject');
if (h = INVALID_HANDLE_VALUE) or (h = 0)
raise Exception.Create('Error!')
else
begin
p := MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);

.........

//在这里对指针p进行读写操作就行了,系统会自动把该文件映射进内存
..........

UnMapViewOfFile(p);
end;
CloseHandle(h);
finally
fs.Free;
end;
 
使用文件映射,由系统进行缓冲和内存文件映射,使用者直接访问内存就行了,
无需编写多余的代码。

程序见上面,加了一句注释。
 
to zzh0918:
你的方法不好。何况也不是那个数组越大越好,应该在 2k 的时候最快,我试过
还是应该用文件映射
 
kyq,你好,因为我对这个概念初次接触,希望你能详细解释一下。
如果想把c:/abc.bin的第5个字节内的数据取出来,这句代码该如何写?
多谢!
 
文件映像的方法是最快的吗?内存流怎么样?
 
把c:/abc.bin的第5个字节内的数据取出来:
var
ch:char;
pp:pchar;
在p := MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);后
pp:=pchar(p);
ch:=(pp+5)^
 
提高大二进制文件的读取速度,还是应该用内存文件映射,
我有控件,你自己安装了.
////////////////////////////////////////////
// The Unofficial Newsletter of Delphi Users - Issue #19 - January 1997
//--------------------------------------------------------------------------------

//Source for Big Bitmaps


// BITMAP VIEWER
// Enables bitmaps which are disc files to be displayed in a
// TImage-like control without loading the bitmap into memory.
// Great for very large bitmaps.

// Grahame Marsh 1996


unit BigGraphic;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics,
Controls, Dialogs, Forms, DsgnIntf;

type
TBMPFilename = type string; // filename will have its owner property editor

type
TBigBitmapViewer = class (TGraphicControl)
private
FFileName: TBMPFilename; // bitmap filename, own type so it can have own prop editor
FPalette : HPalette; // handle to bitmap palette
FData : pointer; // pointer to start of data in memory mapped file
FBitmapWidth, // copy of bitmap width info for convience
FBitmapHeight, // copy of bitmap height info for convience
FColours : integer; // number of colours in palette
FCentre, // centre the bitmap in the control
FStretch, // stretch the bitmap to fill the control
FAutoSize, // automatically size the control to display the bitmap
FActive : boolean; // true opens the viewer, false it's closed
FFileHeader : PBitmapFileHeader; // pointer to TBitmapFileHeader struct
FInfoHeader : PBitmapInfoHeader; // pointer to TBitmapInfoHeader struct
FInfo : PBitmapInfo; // pointer to the TBitmapInfo struct
FPixelStart : pointer; // pointer to the start of the pixel data
procedure SetActive (Value : boolean);
procedure SetAutoSize (Value : boolean);
procedure SetFilename (const Value : TBMPFilename);
procedure SetStretch (Value : boolean);
procedure SetCentre (Value : boolean);
procedure SetDummyInt (Value : integer);
protected
procedure OpenViewer; virtual;
procedure CloseViewer; virtual;
procedure GetPalette;
procedure Paint; override;
procedure Changes; virtual;
public
constructor Create (AOwner : TComponent); override;
destructor Destroy; override;
// open the viewer
procedure Close;
// close the viewer
procedure Open;
// pointer to the file header info
property BitmapFileHeader : PBitmapFileHeader read FFileHeader;
// pointer to the bitmap info header
property BitmapInfoHeader : PBitmapInfoHeader read FInfoHeader;
// pointer to the bitmap info
property BitmapInfo : PBitmapInfo read FInfo;
// pointer to the bitmap pixel data array
property PixelStart : pointer read FPixelStart;
// palette handle
property Palette : HPalette read FPalette;
published
//READ-WRITE PROPS
// size control to bitmap
property AutoSize : boolean read FAutoSize write SetAutoSize default false;
// bitmap centred
property Centre : boolean read FCentre write SetCentre default false;
// filename of bitmap
property Filename : TBMPFilename read FFilename write SetFilename;
// stretch bitmap
property Stretch : boolean read FStretch write SetStretch default false;
// READ-ONLY PROPS
// number of colours in the bitmap palette
property Colours : integer read FColours write SetDummyInt stored false;
// bitmap width
property BitmapHeight : integer read FBitmapHeight write SetDummyInt stored false;
// bitmap height
property BitmapWidth : integer read FBitmapWidth write SetDummyInt stored false;
// TGraphicControl PROPS NOW PUBLISHED
property Align;
property DragCursor;
property DragMode;
property Enabled;
property ParentShowHint;
property PopupMenu;
property ShowHint;
property Visible;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnStartDrag;
// viewer activate - stream active last!
property Active : boolean read FActive write SetActive default false;
end;

// filename property editor .. fileopen dialog box
type
TBMPFilenameProperty = class (TStringProperty)
public
procedure Edit; override;
function GetAttributes: TPropertyAttributes; override;
end;

procedure Register;

implementation

const
BitmapSignature = $4D42;

procedure InvalidBitmap;
begin
raise Exception.Create ('Bitmap image is not valid')
end;

procedure NotWhenActive;
begin
raise Exception.Create ('Not on an active big bitmap viewer')
end;

constructor TBigBitmapViewer.Create (AOwner : TComponent);
begin
inherited Create (AOwner);
Width := 150;
Height := 150
end;

destructor TBigBitmapViewer.Destroy;
begin
CloseViewer; // ensure file view is freed
inherited Destroy
end;

procedure TBigBitmapViewer.GetPalette;
var
SysPalSize,
Loop,
LogSize : integer;
LogPalette : PLogPalette;
DC : HDC;
Focus : HWND;
begin
// fetch palette for colour bitmaps only
if FColours > 2 then
begin

// create palette from bitmap info
LogSize := SizeOf (TLogPalette) + pred(FColours) * SizeOf(TPaletteEntry);
LogPalette := AllocMem (LogSize);
try
with LogPalette^ do
begin
palNumEntries := FColours;
palVersion := $0300;
{$IFOPT R+}
{$DEFINE R_PLUS}
{$R-}
{$ENDIF}
Focus := GetFocus;
DC := GetDC (Focus);
try
SysPalSize := GetDeviceCaps (DC, SIZEPALETTE);
if (FColours = 16) and (SysPalSize >= 16) then
begin
GetSystemPaletteEntries (DC, 0, 8, palPalEntry);
loop := 8;
GetSystemPaletteEntries (DC, SysPalSize - loop, loop, palPalEntry[loop])
end else
with FInfo^ do
for loop := 0 to pred (FColours) do
begin
palPalEntry[loop].peRed := bmiColors[loop].rgbRed;
palPalEntry[loop].peGreen := bmiColors[loop].rgbGreen;
palPalEntry[loop].peBlue := bmiColors[loop].rgbBlue
end
finally
ReleaseDC(Focus, DC)
end
{$IFDEF R_PLUS}
{$R+}
{$UNDEF R_PLUS}
{$ENDIF}
end;
FPalette := CreatePalette (LogPalette^)
finally
FreeMem (LogPalette, LogSize)
end
end
end;

procedure TBigBitmapViewer.OpenViewer;
var
FileHandle,
MapHandle : THandle;
begin
if FActive then exit;

// open file
FileHandle := FileOpen (FFilename, fmOpenRead + fmShareDenyNone);
if FileHandle = INVALID_HANDLE_VALUE then
raise Exception.Create ('Failed to open ' + FFilename);

// create file map
try
MapHandle := CreateFileMapping (FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if MapHandle = 0 then
raise Exception.Create ('Failed to map file')
finally
CloseHandle (FileHandle)
end;

// view file map
try
FData := MapViewOfFile (MapHandle, FILE_MAP_READ, 0, 0, 0);
if FData = nil then
raise Exception.Create ('Failed to view map file')
finally
CloseHandle (MapHandle)
end;

// set pointers into file view
FFileHeader := FData;

// test for valid bitmap file:
if FFileHeader^.bfType <> BitmapSignature then
begin
UnmapViewOfFile (FData);
FData := nil;
InvalidBitmap
end;

// set up a few other pointers
FInfoHeader := pointer (integer (FData) + sizeof (TBitmapFileHeader));
FInfo := pointer (FInfoHeader);
FPixelStart := pointer (integer(FData) + FFileHeader^.bfOffBits);

// get number of colours
with FInfoHeader^ do
if biClrUsed <> 0 then
FColours := biClrUsed
else
case biBitCount of
1,
4,
8 : FColours := 1 shl biBitCount
else
FColours := 0
end;

// get bitmap size into easy to access variables
FBitmapHeight := FInfoHeader^.biHeight;
FBitmapWidth := FInfoHeader^.biWidth;

// fetch the palette
GetPalette;

// other setups
FActive := true;
Changes
end;

procedure TBigBitmapViewer.Paint;
var
OldPalette : HPalette;
Dest : TRect;
begin
with Canvas do
if (csDesigning in ComponentState) and not FActive then
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle (0, 0, Width, Height)
end else begin
if FPalette <> 0 then
OldPalette := SelectPalette (Handle, FPalette, false)
else
OldPalette := 0;

try
RealizePalette (Handle);

if FStretch then
Dest := ClientRect
else
if Centre then
Dest := Rect ((Width - FBitmapWidth) div 2,
(Height - FBitmapHeight) div 2,
FBitmapWidth, FBitmapHeight)
else
Dest := Rect (0, 0, FBitmapWidth, FBitmapHeight);

with Dest do
StretchDIBits (Handle,
Left, Top, Right, Bottom,
0, 0, FBitmapWidth, FBitmapHeight,
FPixelStart, FInfo^,
DIB_RGB_COLORS, SRCCOPY)
finally
if OldPalette <> 0 then
SelectPalette (Handle, OldPalette, false)
end
end
end;

procedure TBigBitmapViewer.CloseViewer;
begin
if FActive then
begin
FActive := false;
if FData <> nil then
begin
UnmapViewOfFile (FData); // remove the memory mapped file view
FData := nil
end;
if FPalette <> 0 then
DeleteObject (FPalette) // free the palette
end
end;

procedure TBigBitmapViewer.Open;
begin
Active := true
end;

procedure TBigBitmapViewer.Close;
begin
Active := false
end;

procedure TBigBitmapViewer.SetActive (Value : boolean);
begin
if Value <> FActive then
if Value then
OpenViewer
else
CloseViewer
end;

procedure TBigBitmapViewer.SetAutoSize (Value : boolean);
begin
if Value <> FAutoSize then
begin
FAutoSize := Value;
Changes
end
end;

procedure TBigBitmapViewer.SetStretch (Value : boolean);
begin
if Value <> FStretch then
begin
FStretch := Value;
Changes
end
end;

procedure TBigBitmapViewer.SetCentre (Value : boolean);
begin
if Value <> FCentre then
begin
FCentre := Value;
Changes
end
end;

procedure TBigBitmapViewer.SetFilename (const Value : TBMPFilename);
begin
if Value <> FFilename then
begin
if FActive then
NotWhenActive;
FFilename := Value
end
end;

procedure TBigBitmapViewer.SetDummyInt (Value : integer);
begin
end;

procedure TBigBitmapViewer.Changes;
begin
if (BitmapWidth >= Width) and (BitmapHeight >= Height) then
ControlStyle := ControlStyle + [csOpaque]
else
ControlStyle := ControlStyle - [csOpaque];

if AutoSize and (BitmapWidth > 0) and (BitmapHeight > 0) then
SetBounds (Left, Top, BitmapWidth, BitmapHeight)
else
Invalidate
end;

//--- filename property editor

procedure TBMPFilenameProperty.Edit;
begin
with TOpenDialog.Create(Application) do
begin
Filename := GetValue;
Filter := 'Windows bitmaps (*.BMP)|*.BMP';
Options := Options + [ofPathMustExist, ofFileMustExist, ofHideReadOnly];
try
if Execute then
SetValue(Filename)
finally
Free
end
end
end;

function TBMPFilenameProperty.GetAttributes: TPropertyAttributes;
begin
Result := [paDialog, paRevertable]
end;

// - register component and filename editor

procedure Register;
begin
RegisterComponents ('Custom', [TBigBitmapViewer]);
RegisterPropertyEditor (TypeInfo (TBMPFilename), nil, '', TBMPFilenameProperty);
end;

end.


//Return to Article
//Return to Component Cookbook

//Return to Front Page
/////////////////////////////
具体使用 :
BigBitmapViewer.FileName :=OpenPictureDialog.FileName;
BigBitmapViewer.Active :=True;
/////////////////////// ok !
 
概念和使用方法
至于可以看看http://www.delphibbs.com/delphibbs/dispq.asp?lid=519290。

把c:/abc.bin的第5个字节内的数据取出来:
var
ch:Char;
在注释处
ch:=(PChar(p)+4)^;

To yth:
是4吧?
 
kyq,你好,按照你的方法写了一段程序,执行到
h := CreateFileMapping(fs.Handle, nil, PAGE_READWRITE,0, 0, 'MyFileMappingObject'
时,h始终为0,这是为何?

procedure TForm1.Button1Click(Sender: TObject);
var
h:Integer; p:Pointer;
ch:Char; fs:TFileStream;
begin
fs:=TFileStream.Create('G:/ssa00004.bin',fmOpenRead);
try
h := CreateFileMapping(fs.Handle, nil, PAGE_READWRITE,0, 0, 'MyFileMappingObject');
if (h = INVALID_HANDLE_VALUE) or (h = 0) then
raise Exception.Create('Error!')
else
begin
p := MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
ch:=(PChar(p)+4)^;
showmessage(ch);
//在这里对指针p进行读写操作就行了,系统会自动把该文件映射进内存
UnMapViewOfFile(p);
end;
CloseHandle(h);
finally
fs.Free;
end;
end;
 
改了一下,忘了用独占方式打开。:P

我就要去旅行,7号才回来。

procedure TForm1.Button1Click(Sender: TObject);
var
h:Cardinal;
p:Pointer;
ch:Char;
fs:TFileStream;
begin
fs:=TFileStream.Create('C:/comp-nsxqz-104.mp3',fmOpenReadWrite or fmShareExclusive);
try
h := CreateFileMapping(fs.Handle, nil, PAGE_READWRITE,0, 0,nil);
if (h = INVALID_HANDLE_VALUE) or (h = 0) then
raise Exception.Create('Error!')
else
begin
try
p := MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0);
try
ch:=(PChar(p)+1344)^;
showmessage(IntToStr(Ord(ch)));
finally
UnMapViewOfFile(p);
end;
finally
CloseHandle(h);
end;
end;
finally
fs.Free;
end;
end;
 
多人接受答案了。
 
后退
顶部