Board index » delphi » BlockRead, TFileStream incompatible with Dynamic Arrays?

BlockRead, TFileStream incompatible with Dynamic Arrays?

Hi

I'm trying to read binary files of unknown sizes into a Dynamic array,
in ONE go.  Unfortunately, this does not seem to be possible with
Dynamic arrays.

The following code raises an EInOutError exception, I/O error 87.

procedure TForm1.Button1Click(Sender: TObject);
var
 Buf: array of byte;
 Size, Read: integer;
 f: file;
begin
 AssignFile(f, 'foo.bar');
 Reset(f, 1);
 Size:=FileSize(f);
 SetLength(Buf, Size);
 BlockRead(f, Buf, Size, Read);
 CloseFile(f);
end;

I also tried using a TFileStream, but had a similar problem:

procedure TForm1.Button2Click(Sender: TObject);
var
 Buf: array of byte;
 sf: TFileStream;
 Size: integer;
begin
 sf:=TFileStream.Create('foo.bar', fmOpenRead);
 Size:=sf.Size;
 SetLength(Buf, Size);
 sf.ReadBuffer(Buf, Size);
 sf.Destroy;
end;

It seems that BlockRead and TFileStream.ReadBuffer are unable to
detect the size of dynamic arrays correctly.

Any advice is appreciated.

Gary Comer

 

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


you are miss using the array.
 i am surprised you haven't had a memory leak or fault by now..
try this.
type MpByte = array[0..0] of byte;
var
  buf :^Mpbyte;
  Size:integer;
Begin
  AssugFile(F,'adasda');
  reset(F, 1);
 Size := FileSize(F);
 getmem(Buf, Size);
 blockRead(f, Buf^, Size);
 // to access the memory....
 Buf[0...Size-1] := ? ect...
// when done.
 FreeMem(Buf, size);
closeFile(F);
Quote
Gary Comer wrote:
> Hi

> I'm trying to read binary files of unknown sizes into a Dynamic array,
> in ONE go.  Unfortunately, this does not seem to be possible with
> Dynamic arrays.

> The following code raises an EInOutError exception, I/O error 87.

> procedure TForm1.Button1Click(Sender: TObject);
> var
>  Buf: array of byte;
>  Size, Read: integer;
>  f: file;
> begin
>  AssignFile(f, 'foo.bar');
>  Reset(f, 1);
>  Size:=FileSize(f);
>  SetLength(Buf, Size);
>  BlockRead(f, Buf, Size, Read);
>  CloseFile(f);
> end;

> I also tried using a TFileStream, but had a similar problem:

> procedure TForm1.Button2Click(Sender: TObject);
> var
>  Buf: array of byte;
>  sf: TFileStream;
>  Size: integer;
> begin
>  sf:=TFileStream.Create('foo.bar', fmOpenRead);
>  Size:=sf.Size;
>  SetLength(Buf, Size);
>  sf.ReadBuffer(Buf, Size);
>  sf.Destroy;
> end;

> It seems that BlockRead and TFileStream.ReadBuffer are unable to
> detect the size of dynamic arrays correctly.

> Any advice is appreciated.

> Gary Comer

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


Your array Buf points to the array structure not the data. Buf[0] will
give you the start of the data.

BlockRead(f, Buf[0], Size, Read);

Should work.

Mitch Wolberg,
RockWare, Inc.

Quote
Gary Comer wrote:

> Hi

> I'm trying to read binary files of unknown sizes into a Dynamic array,
> in ONE go.  Unfortunately, this does not seem to be possible with
> Dynamic arrays.

> The following code raises an EInOutError exception, I/O error 87.

> procedure TForm1.Button1Click(Sender: TObject);
> var
>  Buf: array of byte;
>  Size, Read: integer;
>  f: file;
> begin
>  AssignFile(f, 'foo.bar');
>  Reset(f, 1);
>  Size:=FileSize(f);
>  SetLength(Buf, Size);
>  BlockRead(f, Buf, Size, Read);
>  CloseFile(f);
> end;

> I also tried using a TFileStream, but had a similar problem:

> procedure TForm1.Button2Click(Sender: TObject);
> var
>  Buf: array of byte;
>  sf: TFileStream;
>  Size: integer;
> begin
>  sf:=TFileStream.Create('foo.bar', fmOpenRead);
>  Size:=sf.Size;
>  SetLength(Buf, Size);
>  sf.ReadBuffer(Buf, Size);
>  sf.Destroy;
> end;

> It seems that BlockRead and TFileStream.ReadBuffer are unable to
> detect the size of dynamic arrays correctly.

> Any advice is appreciated.

> Gary Comer

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


Quote
Gary Comer wrote:
> Hi

> I'm trying to read binary files of unknown sizes into a Dynamic array,
> in ONE go.

Dynamic array variables are actually pointers.  If you pass it to
BlockRead it will not write to the actual data.

 BlockRead(f, Pointer(Buf)^, Size, Read);

Quote
> I also tried using a TFileStream, but had a similar problem:

    sf.ReadBuffer(Pointer(Buf)^, Size);

--
Bob Lee
High Performance Delphi - http://www.econos.com/optimize/
Updated August 2

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


Quote
On Mon, 16 Aug 1999 09:26:13 -0600, in alt.lang.delphi you wrote:
>Your array Buf points to the array structure not the data. Buf[0] will
>give you the start of the data.

>BlockRead(f, Buf[0], Size, Read);

>Should work.

>Mitch Wolberg,
>RockWare, Inc.

Mitch -

Great, works a treat.  Thanks.

-Gary

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


On Mon, 16 Aug 1999 09:59:54 -0400, Maynard Philbrook

Quote
<ja...@{*word*104}zone.net> wrote:
>you are miss using the array.
> i am surprised you haven't had a memory leak or fault by now..
>try this.
>type MpByte = array[0..0] of byte;
>var
>  buf :^Mpbyte;
>  Size:integer;
>Begin
>  AssugFile(F,'adasda');
>  reset(F, 1);
> Size := FileSize(F);
> getmem(Buf, Size);
> blockRead(f, Buf^, Size);
> // to access the memory....
> Buf[0...Size-1] := ? ect...
>// when done.
> FreeMem(Buf, size);
>closeFile(F);

Thanks, but I don't think you actually tried compiling this code.  Any
element except zero will violate the boundary of the array...

-Gary

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


On Mon, 16 Aug 1999 10:34:20 -0500, in comp.lang.pascal.delphi.misc

Quote
you wrote:
>Dynamic array variables are actually pointers.  If you pass it to
>BlockRead it will not write to the actual data.

> BlockRead(f, Pointer(Buf)^, Size, Read);

>> I also tried using a TFileStream, but had a similar problem:

>    sf.ReadBuffer(Pointer(Buf)^, Size);

Thanks, this seems to work fine.  However, to access array elements,
you do not need to deference the pointer, i.e.

Buf[55]:=76;

This works, whereas...

Pointer(Buf)^[55]:=76;

...does not.  Confusing!

Also, being as this is dynamic memory, do I need to dispose of it when
I am finished?  What will happen if I use SetLength to use a different
size of memory?

Thanks again.

-Gary

Re:BlockRead, TFileStream incompatible with Dynamic Arrays?


JRS:  In article <37B8195A.FE04E...@{*word*104}zone.net> of Mon, 16 Aug 1999
09:59:54 in news:comp.lang.pascal.delphi.misc, Maynard Philbrook
Quote
<ja...@{*word*104}zone.net> wrote:
>you are miss using the array.
> i am surprised you haven't had a memory leak or fault by now..
>try this.
>type MpByte = array[0..0] of byte;

                        ^ // that one

Quote
>var
>  buf :^Mpbyte;
>  Size:integer;
>Begin
>  AssugFile(F,'adasda');
>  reset(F, 1);
> Size := FileSize(F);
> getmem(Buf, Size);
> blockRead(f, Buf^, Size);
> // to access the memory....
> Buf[0...Size-1] := ? ect...
>// when done.
> FreeMem(Buf, size);
>closeFile(F);

In such code, the value indicated above should not be zero, but should
be as large as possible.  In that case, the program can still run with
Range Checking on, however Buf is used later.

IMHO, all run-time checks should be turned on at all times, except when
you're certain that they're not needed, and you're right about that, and
the code in question contributes significantly to run duration or code
size.  It saves a lot of human debug time.

http://www.merlyn.demon.co.uk/pas-extn.htm#VLarrs is substantially
applicable, though written for BP7.

--
 ? John Stockton, Surrey, UK.  j...@merlyn.demon.co.uk   Turnpike v4.00   MIME. ?
  <URL: http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c. FAQqish topics, links.
  Timo's TurboPascal <A HREF="ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip">FAQ</A>.
  <A HREF="http://www.merlyn.demon.co.uk/clpb-faq.txt">Mini-FAQ</A> of c.l.p.b.

Other Threads