Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2009-01

TFileStream

23 messages · 10 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Dave Coventry

I've started using TFileStream since posting a query here, but I'd like to know a bit more about it.

Is there somewhere that I can find information on how to use it?

Specifically, if I load a file into an array as follows:

FS:=TFileStream.Create(fname, fmshareDenyWrite);
FS.ReadBuffer(fsbuffer,recsize);

can I alter the array and then save the altered array back into the file?

do I just write the entire array back?

fsbuffer[128]:=56;
fsbuffer[132]:=42;
FS.WriteBuffer(fsbuffer,recsize);

or is there a better way?

Reply by email

Andrew Brunner
to Dave Coventry

You could c write specific calls to write a byte or segment of contiguous bytes.

FS.Seek(128,soFromBegining);
FS.WriteBuffer(fsBuffer[128],1);
FS.Seek(132,soFromBegining);
FS.WriteBuffer(fsBuffer[132],1);
Dave Coventry wrote 25 lines
I've started using TFileStream since posting a query here, but I'd like to know a bit more about it. Is there somewhere that I can find information on how to use it? Specifically, if I load a file into an array as follows: FS:=TFileStream.Create(fname, fmshareDenyWrite); FS.ReadBuffer(fsbuffer,recsize); can I alter the array and then save the altered array back into the file? do I just write the entire array back? fsbuffer[128]:=56; fsbuffer[132]:=42; FS.WriteBuffer(fsbuffer,recsize); or is there a better way? _______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Dave Coventry
to Andrew Brunner

How about if you wanted to change the contents of the start of a file? Does it work if you seek to the start of the file and write a couple of bytes, say, or do you have to rewrite the entire file?

2009/1/7 Andrew Brunner :

Show quoted text 41 lines
You could c write specific calls to write a byte or segment of contiguous bytes. FS.Seek(128,soFromBegining); FS.WriteBuffer(fsBuffer[128],1); FS.Seek(132,soFromBegining); FS.WriteBuffer(fsBuffer[132],1); On Tue, Jan 6, 2009 at 7:55 PM, Dave Coventry wrote: > I've started using TFileStream since posting a query here, but I'd > like to know a bit more about it. > > Is there somewhere that I can find information on how to use it? > > Specifically, if I load a file into an array as follows: > > FS:=TFileStream.Create(fname, fmshareDenyWrite); > FS.ReadBuffer(fsbuffer,recsize); > > can I alter the array and then save the altered array back into the file? > > do I just write the entire array back? > > fsbuffer[128]:=56; > fsbuffer[132]:=42; > FS.WriteBuffer(fsbuffer,recsize); > > > or is there a better way? > _______________________________________________ > Lazarus mailing list > > http://www.lazarus.freepascal.org/mailman/listinfo/lazarus > _______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Bart
to Dave Coventry
Dave Coventry wrote
How about if you wanted to change the contents of the start of a file? Does it work if you seek to the start of the file and write a couple of bytes, say, or do you have to rewrite the entire file?

Yes it will work. You will overwrite the existing data that were in that location (as you'ld probably know already).

Bart

Reply by email

Dave Coventry
to Bart

I'm having some difficulty over this:

============= snip ===================
  FS:=TFileStream.Create(fname, fmshareDenyWrite);
  Try
    FS.ReadBuffer(hdbuffer[0],32);
  Finally
    FreeAndNil(FS);
  end;
  RecSize:=LEtoN(PSmallInt(@hdbuffer[10])^);
  SetLength(recbuffer,RecSize);
  FillChar(recbuffer,RecSize,' ');
  pos:=68;
  bufferpos:=1;
  setLength(fldheader,48);
  for i:=0 to gFields.Count-1 do
  begin
    ftype:=getFieldType(PChar(gFields.GetItem(i)));
    case ftype of
      43://'+'
      begin
        FS:=TFileStream.Create(fname, fmshareDenyWrite);<----- Fails here
        Try
          FS.Seek(pos,soFromBeginning);
          FS.ReadBuffer(fldheader[0],4);
        Finally
          FreeAndNil(FS);
        end;
      end;
============= snip ===================

Project raised exception class 'External: SIGSEgV'

Followed by:

Project raised exception class 'RunError (216)'
'Access Violation'

What am I doing wrong?

Reply by email

ajv
to Dave Coventry

Dear Dave Coventry,

Probably the FileStream still exist in an other thread. Application.ProcessMessages might help.
Better is it to open the stream on fname once an reposition the pointer repeatedly.

Success.

=============================================================

Show quoted text 46 lines
I'm having some difficulty over this: ============= snip =================== FS:=TFileStream.Create(fname, fmshareDenyWrite); Try FS.ReadBuffer(hdbuffer[0],32); Finally FreeAndNil(FS); end; RecSize:=LEtoN(PSmallInt(@hdbuffer[10])^); SetLength(recbuffer,RecSize); FillChar(recbuffer,RecSize,' '); pos:=68; bufferpos:=1; setLength(fldheader,48); for i:=0 to gFields.Count-1 do begin ftype:=getFieldType(PChar(gFields.GetItem(i))); case ftype of 43://'+' begin FS:=TFileStream.Create(fname, fmshareDenyWrite);<----- Fails here Try FS.Seek(pos,soFromBeginning); FS.ReadBuffer(fldheader[0],4); Finally FreeAndNil(FS); end; end; ============= snip =================== Project raised exception class 'External: SIGSEgV' Followed by: Project raised exception class 'RunError (216)' 'Access Violation' What am I doing wrong? _______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Dave Coventry
to ajv

Hi AJ.

I was under the impression that this:

 FS:=TFileStream.Create(fname, fmshareDenyWrite);
 Try
   FS.ReadBuffer(hdbuffer[0],32);
 Finally
   FreeAndNil(FS);<-----
 end;

would free the File Pointer to be used again.

Do you suggest that I use another variable when I do it the second time?

Is it possible to specify that the program only uses one thread?

I'm having a lot of unexplained errors in developing this app and I'm wondering if this isn't the cause of a lot of them.

FS2:=TFileStream.Create(fname, fmshareDenyWrite);

Surely that would fail too?

2009/1/26 ajv :

Show quoted text 8 lines
Dear Dave Coventry, Probably the FileStream still exist in an other thread. Application.ProcessMessages might help. Better is it to open the stream on fname once an reposition the pointer repeatedly. Success.

Reply by email

Michael Van Canneyt
to Dave Coventry
Dave Coventry wrote 12 lines
Hi AJ. I was under the impression that this: FS:=TFileStream.Create(fname, fmshareDenyWrite); Try FS.ReadBuffer(hdbuffer[0],32); Finally FreeAndNil(FS);<----- end; would free the File Pointer to be used again.

That is correct.

Do you suggest that I use another variable when I do it the second time?

That should absolutely not be necessary.

Is it possible to specify that the program only uses one thread?

This is so by default, unless you create threads yourself ?

More likely is simply the fact that the file cannot be locked.

Michael.

Reply by email

Dave Coventry
to Michael Van Canneyt

Hi Michael.

The file is accessed correctly the first time, but fails the second time.

2009/1/26 Michael Van Canneyt :

This is so by default, unless you create threads yourself ?

No, I didn't.

More likely is simply the fact that the file cannot be locked.

How can I check this?

Reply by email

Michael Van Canneyt
to Dave Coventry
Dave Coventry wrote 12 lines
Hi Michael. The file is accessed correctly the first time, but fails the second time. 2009/1/26 Michael Van Canneyt : > This is so by default, unless you create threads yourself ? No, I didn't. > More likely is simply the fact that the file cannot be locked. How can I check this?

Well, RaiseLastOSError should give more information.

Michael.

Reply by email

ajv
to Michael Van Canneyt: That is correct. That should absolutely not be necessary. This is so by default, unless…

The application is one thread, the file handling is done by the operating system in an other thread.
FreeAndNil releases indded the Class TFileStream but the OS can still have a capture on the file.
This will not happen if you use one instance of an attached class throughout your application.

Succes, Anthony Vogelaar.

============================================================================

Show quoted text 41 lines
On Mon, 26 Jan 2009, Dave Coventry wrote: > Hi AJ. > > I was under the impression that this: > > FS:=TFileStream.Create(fname, fmshareDenyWrite); > Try > FS.ReadBuffer(hdbuffer[0],32); > Finally > FreeAndNil(FS);<----- > end; > > would free the File Pointer to be used again. > That is correct. > Do you suggest that I use another variable when I do it the second time? > That should absolutely not be necessary. > Is it possible to specify that the program only uses one thread? > This is so by default, unless you create threads yourself ? More likely is simply the fact that the file cannot be locked. Michael. _______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Mattias Gaertner
to Dave Coventry: I'm having some difficulty over this: ============= snip ===================…
Show quoted text 12 lines
I'm having some difficulty over this: ============= snip =================== FS:=TFileStream.Create(fname, fmshareDenyWrite); Try FS.ReadBuffer(hdbuffer[0],32); Finally FreeAndNil(FS); end; RecSize:=LEtoN(PSmallInt(@hdbuffer[10])^); SetLength(recbuffer,RecSize); FillChar(recbuffer,RecSize,' ');

Maybe you mean
FillChar(recbuffer^,RecSize,' ');
?

Show quoted text 27 lines
pos:=68; bufferpos:=1; setLength(fldheader,48); for i:=0 to gFields.Count-1 do begin ftype:=getFieldType(PChar(gFields.GetItem(i))); case ftype of 43://'+' begin FS:=TFileStream.Create(fname, fmshareDenyWrite);<----- Fails here Try FS.Seek(pos,soFromBeginning); FS.ReadBuffer(fldheader[0],4); Finally FreeAndNil(FS); end; end; ============= snip =================== Project raised exception class 'External: SIGSEgV' Followed by: Project raised exception class 'RunError (216)' 'Access Violation' What am I doing wrong?

Mattias

Reply by email

Hans-Peter Diettrich
to Dave Coventry: I'm having some difficulty over this: ============= snip ===================…
FS:=TFileStream.Create(fname, fmshareDenyWrite);

IMO you should also specify the requested access (fmCreate or fmOpen...), even if zero happens to mean fmOpenRead.

Nonetheless it looks strange when the same file cannot be reopened later. Are you sure that fname is unchanged the second time?

Why don't you keep the stream open, and move the try/finally to the end of the subroutine?

DoDi

Reply by email

JoshyFun
to Dave Coventry: I'm having some difficulty over this: ============= snip ===================…

Hello Dave,

Monday, January 26, 2009, 2:49:24 PM, you wrote:

DC>     FS.ReadBuffer(hdbuffer[0],32);
DC>   FillChar(recbuffer,RecSize,' ');
DC>         FS:=TFileStream.Create(fname,
DC> fmshareDenyWrite);<----- Fails here

DC> Project raised exception class 'External: SIGSEgV'

I'm 99% sure that one of upper lines is wrong. This kind of errors are usually related with unwanted stack variables write, like reading beyong limits, assigning a variable adress instead the value that points that variable. Recheck that lines.

Best regards, JoshyFun

Reply by email

Vincent Snijders
to Mattias Gaertner: On Mon, 26 Jan 2009 15:49:24 +0200 Maybe you mean FillChar(recbuffer^,RecSize,' '); ?…

2009/1/26, Mattias Gaertner :

Show quoted text 24 lines
On Mon, 26 Jan 2009 15:49:24 +0200 Dave Coventry wrote: > I'm having some difficulty over this: > > ============= snip =================== > FS:=TFileStream.Create(fname, fmshareDenyWrite); > Try > FS.ReadBuffer(hdbuffer[0],32); > Finally > FreeAndNil(FS); > end; > RecSize:=LEtoN(PSmallInt(@hdbuffer[10])^); > SetLength(recbuffer,RecSize); > FillChar(recbuffer,RecSize,' '); Maybe you mean FillChar(recbuffer^,RecSize,' '); ?
Or FillChar(recbuffer[1],RecSize,' ');

if it is a string or [0] if it is a dynarray.

Vincent

Reply by email

Dave Coventry
to Vincent Snijders

2009/1/26 Vincent Snijders :

Show quoted text 10 lines
2009/1/26, Mattias Gaertner : > Maybe you mean > > FillChar(recbuffer^,RecSize,' '); > ? > Or FillChar(recbuffer[1],RecSize,' '); if it is a string or [0] if it is a dynarray.

Thanks.

I'll put that in. It seemed to work okay as written but I obviously never had the opportunity to check the output.

I'll have a go at twisting the code around to see if I can get the calls to the file stream in the same 'try' block.

Reply by email

Andrew Brunner
to Dave Coventry

Actually, I'm thinking you're creating a memory problem with using fillchar and passing the pointer to the dynarray instead of the element. Try using FillChar with the zero element again... The reason why the construction maybe failing is b/c a potential memory leak created by not using the zero element of the dynarray you are using.

Dave Coventry wrote 24 lines
2009/1/26 Vincent Snijders : > 2009/1/26, Mattias Gaertner : >> Maybe you mean >> >> FillChar(recbuffer^,RecSize,' '); >> ? >> > > Or FillChar(recbuffer[1],RecSize,' '); > > if it is a string or [0] if it is a dynarray. Thanks. I'll put that in. It seemed to work okay as written but I obviously never had the opportunity to check the output. I'll have a go at twisting the code around to see if I can get the calls to the file stream in the same 'try' block. _______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Dave Coventry
to Andrew Brunner

2009/1/26 Andrew Brunner :

Show quoted text 6 lines
Actually, I'm thinking you're creating a memory problem with using fillchar and passing the pointer to the dynarray instead of the element. Try using FillChar with the zero element again... The reason why the construction maybe failing is b/c a potential memory leak created by not using the zero element of the dynarray you are using.

So you're saying that if I miss out the Fillchar function, it will work a expected? Apart from the fact that my array won't be filled with spaces, of course.

Reply by email

Michael Van Canneyt
to Dave Coventry
Dave Coventry wrote 11 lines
2009/1/26 Andrew Brunner : > Actually, I'm thinking you're creating a memory problem with using > fillchar and passing the pointer to the dynarray instead of the > element. Try using FillChar with the zero element again... The > reason why the construction maybe failing is b/c a potential memory > leak created by not using the zero element of the dynarray you are > using. So you're saying that if I miss out the Fillchar function, it will work a expected? Apart from the fact that my array won't be filled with spaces, of course.

That is what he is saying, yes.

Michael.

Reply by email

Dave Coventry
to Dave Coventry
============= snip ===================
   case ftype of
     43://'+'
     begin
       FS:=TFileStream.Create(fname, fmshareDenyWrite);
       Try
         FS.Seek(pos,soFromBeginning);
         FS.ReadBuffer(fldheader[0],4);
         increm:=LEtoN(PLongInt(fldheader)^)+1;
         for m:=0 to 3 do
         begin
           fldheader[m]:=increm and 255;
           increm:=increm shr 8;
         end;
          FS.Seek(pos,soFromBeginning);
          FS.WriteBuffer(fldheader[0],4); <----- Fails here
       Finally
         FreeAndNil(FS);
       end;
     end;
   end;
============= snip ===================

Continuing on the same block:

I am trying to read a block of 4 bytes, increment it by one and write it back again.

However, if fails on the write.

Reply by email

Michael Van Canneyt
to Dave Coventry
Dave Coventry wrote 29 lines
============= snip =================== case ftype of 43://'+' begin FS:=TFileStream.Create(fname, fmshareDenyWrite); Try FS.Seek(pos,soFromBeginning); FS.ReadBuffer(fldheader[0],4); increm:=LEtoN(PLongInt(fldheader)^)+1; for m:=0 to 3 do begin fldheader[m]:=increm and 255; increm:=increm shr 8; end; FS.Seek(pos,soFromBeginning); FS.WriteBuffer(fldheader[0],4); <----- Fails here Finally FreeAndNil(FS); end; end; end; ============= snip =================== Continuing on the same block: I am trying to read a block of 4 bytes, increment it by one and write it back again. However, if fails on the write.

Probably because you failed to specify fmOpenReadWrite. fmshareDenyWrite does not automatically mean write access.

Michael.

Show quoted text 5 lines
_______________________________________________ Lazarus mailing list http://www.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Paul Ishenin
to Dave Coventry: ============= snip =================== case ftype of 43://'+' begin…

Dave Coventry wrote:
...

FS:=TFileStream.Create(fname, fmshareDenyWrite);

...

I am trying to read a block of 4 bytes, increment it by one and write it back again. However, if fails on the write.

Please read carefully what have you written:

FS := TFileStream.Create(fname, fmShareDenyWrite);

you passed only fmShareDenyWrite but you have not told to the file stream that you want to write :)

There are few modes in which you can open your stream:

   fmCreate        = $FFFF;
   fmOpenRead      = 0;
   fmOpenWrite     = 1;
   fmOpenReadWrite = 2;

You had not passed any of them => you passed 0 = fmOpenRead. As result you can only read.

If you want to read and write then pass fmOpenReadWrite as mode:

FS := TFileStream.Create(fname, fmOpenReadWrite or fmShareDenyWrite);

Best regards,
Paul Ishenin.

Reply by email