[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]
{
From: tfiske@delphi.com (Todd Fiske)
I've got a huge unit that I've put together over the years that does this,
but I'm not really ready to part with it. I'm happy to trade some tips
though.
The easiest way to start is with text files under 64K, for which you don't
have to worry about lines crossing the buffer boundary. Get the size of the
file, then allocate an array on the heap of that size and blockread the file
into it. Then use a function that reads from the current position up to the
next CR and/or LF and returns all of that as a string. Here's a simple
example of this:
{------------------------------------------------}
{- bintext.pas - binary text file example -}
{- Todd Fiske (tfiske@delphi.com) - 09/28/1994 -}
{------------------------------------------------}
program bintext;
uses
dos;
const
CR = #13;
LF = #10;
{------------------------------------------------}
{- input structure definition & base routines -}
{------------------------------------------------}
type
big_array = array[0..65519] of byte;
big_ptr = ^big_array;
input_buffer = record
data : big_ptr;
size : word;
curr : word;
end;
input_ptr = ^input_buffer;
procedure start_input(var i : input_ptr; size : word);
begin
if i = nil then begin
new(i); { create structure }
i^.size := size;
GetMem(i^.data, i^.size); { create array (could test MemAvail) }
fillchar(i^.data^, i^.size, 0); { initialize }
i^.curr := 0;
end;
end;
procedure stop_input(var i : input_ptr);
begin
if i <> nil then begin
FreeMem(i^.data, i^.size); { done with array }
dispose(i); { done with structure }
i := nil;
end;
end;
procedure load_input(i : input_ptr; s : string);
var
f : file;
begin
assign(f, s); { set filename }
reset(f, 1); { open with record length 1 }
blockread(f, i^.data^, i^.size); { read in file - should test IOResult }
close(f);
end;
{------------------------------------------------}
{- low level access routines -}
{------------------------------------------------}
function curr_char(i : input_ptr) : char;
begin
curr_char := char(i^.data^[i^.curr]);
end;
procedure next_char(i : input_ptr);
begin
inc(i^.curr);
end;
function curr_pos(i : input_ptr) : word;
begin
curr_pos := i^.curr;
end;
function end_of_input(i : input_ptr) : boolean;
begin
end_of_input := i^.curr >= i^.size;
end;
{------------------------------------------------}
{- medium level access -}
{------------------------------------------------}
function get_line(i : input_ptr) : string;
var
w : string;
stt : word;
len : byte;
begin
stt := curr_pos(i);
while (not (curr_char(i) in [CR, LF])) and (not end_of_input(i)) do
next_char(i);
{- testing for both CR and LF here allows reading of Unix files -}
len := curr_pos(i) - stt; { determine length read }
move(i^.data^[stt], w[1], len); { copy into work string }
w[0] := char(len); { set work string length }
if curr_char(i) = CR then next_char(i); { skip line-end chars }
if curr_char(i) = LF then next_char(i);
get_line := w; { return work string }
end;
{------------------------------------------------}
{- main program -}
{------------------------------------------------}
var
sr : SearchRec;
i : input_ptr;
line : string;
begin
writeln;
writeln('BinText - binary textfile example');
if paramcount = 0 then begin { check command line }
writeln;
writeln('usage: bintext <filename>');
halt;
end;
FindFirst(paramstr(1), AnyFile, sr); { test input file }
if DOSError <> 0 then begin
writeln(paramstr(1), ' not found');
halt;
end;
if sr.size > 65520 then begin
writeln(sr.name, ' : ', sr.size, ' bytes - too big (65520 bytes max)');
halt;
end;
i := nil; { load, read, and close }
start_input(i, sr.size);
load_input(i, sr.name);
while not end_of_input(i) do begin
line := get_line(i);
writeln(line);
end;
stop_input(i);
end.
{------------------------------------------------}
{- eof -}
{------------------------------------------------}
{
This array-of-char file handling can be very flexible. I've included routines
in my own to do things like skip whitespace, skip while in a particular groups
of characters, skip until in a group of characters, get-while and get-until
routines, etc. Another thing you can do is save the byte start position of each
line, and jump right to that line by setting i^.curr. What's more, the same
basic methods work on binary files as well.
}
[Back to TEXTFILE SWAG index] [Back to Main SWAG index] [Original]