Recent

Author Topic: Array of TMemorystream  (Read 6853 times)

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Array of TMemorystream
« on: November 20, 2017, 04:07:12 pm »
I try fo build an cache for fast loading images. So I use Tmemorystream and try to build an array but get always an SIGSEGV-Error.
So I enclose 2 Scripts. The first one runs nicely. The seond one shows what I intend to do. I tryed a lot of other coding for that array but not one did succed.
On the oter hand is there a better way to write such a chache?

This works
Code: Pascal  [Select][+][-]
  1. var
  2.   fff: TFilestream;
  3.   mmm:TMemorystream;
  4.  
  5. procedure TForm1.Button4Click(Sender: TObject);
  6. var i: integer;
  7. begin
  8.         for i := 1 to 1 do begin
  9.                 fff := TFilestream.create(filename, fmOpenRead or fmShareDenyWrite);
  10.  
  11.                 //write filestream to memorystream     
  12.                 mmm := TMemorystream.create;  
  13.                 mmm.write(fff,fff.size);
  14.  
  15.                 //write memorystream back to filestream
  16.                 fff.write(mmm,mmm.size);
  17.  
  18.                 Image1.Picture.LoadFromStream(fff);
  19.         end;
  20. end;

This fails
Code: Pascal  [Select][+][-]
  1. var
  2.   fff: TFilestream;
  3.   mmm:TMemorystream;
  4.   cache: array of TMemorystream;
  5.  
  6. procedure TForm1.Button4Click(Sender: TObject);
  7. var i: integer;
  8. begin
  9.         for i := 1 to 1 do begin
  10.                 fff := TFilestream.create(filename, fmOpenRead or fmShareDenyWrite);
  11.  
  12.                 //write filestream to memorystream     
  13.                 cache[0] := TMemorystream.create;  
  14.                 cache[0].write(fff,fff.size);
  15.  
  16.                 //write memorystream back to filestream
  17.                 fff.write(cache[0],cache[0].size);
  18.  
  19.                 Image1.Picture.LoadFromStream(fff);
  20.         end;
  21. end;

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Array of TMemorystream
« Reply #1 on: November 20, 2017, 04:12:35 pm »
Are you serious?
Code: Pascal  [Select][+][-]
  1. //write filestream to memorystream    
  2.                 cache[0] := TMemorystream.create;  
  3.                 cache[0].write(fff,fff.size);
  4.  

Do you mean:

Code: Pascal  [Select][+][-]
  1. //write filestream to memorystream    
  2.                 cache[i] := TMemorystream.create;  
  3.                 cache[i].write(fff,fff.size);
  4.  


There's more bugs but start from there.... Also why use an array 1..1..... That's plain silly..
« Last Edit: November 20, 2017, 04:14:12 pm by Thaddy »
Specialize a type, not a var.

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #2 on: November 20, 2017, 04:16:02 pm »
I Just do it for one entry at the moment so 0 should be ok - later I increase it for sure!!!
Thats not the problem!

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Array of TMemorystream
« Reply #3 on: November 20, 2017, 04:16:19 pm »
Do you mean:
TS probably went from (failing) index variable to a static index in order to verify ?

@ratmalwer:
Read about dynamic array's.

You have to set the 'size' (actually length) of the array at runtime _or_ define you cache variable as a static array.

eduit: So when you write:
I Just do it for one entry at the moment so 0 should be ok - later I increase it for sure!!!
Thats not the problem!
Then it seems to me that you did perhaps not fully understood how arrays work.
« Last Edit: November 20, 2017, 04:20:07 pm by molly »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Array of TMemorystream
« Reply #4 on: November 20, 2017, 04:20:48 pm »
Code: Pascal  [Select][+][-]
  1. var
  2.   fff: TFilestream;
  3.   mmm:TMemorystream;
  4.  
  5. procedure TForm1.Button4Click(Sender: TObject);
  6. var i: integer;
  7. begin
  8.    for i := 1 to 1 do begin
  9.       fff := TFilestream.create(filename, fmOpenReadWrite or fmShareDenyWrite);//You can't write on a read only stream.
  10.  
  11.       //write filestream to memorystream  
  12.             mmm := TMemorystream.create;  
  13.            mmm.write(fff,fff.size);
  14.  
  15.       fff.position := 0;
  16.  
  17.       //write memorystream back to filestream
  18.       fff.write(mmm,mmm.size);
  19.  
  20.       fff.Position  := 0;
  21.  
  22.       Image1.Picture.LoadFromStream(fff);
  23.    end;
  24. end;


Code: Pascal  [Select][+][-]
  1. var
  2.   fff: TFilestream;
  3.   mmm:TMemorystream;
  4.   cache: array of TMemorystream;
  5.  
  6. procedure TForm1.Button4Click(Sender: TObject);
  7. var i: integer;
  8. begin
  9.    setLength(Cache,1);//or 10 depends on your number of cached images.
  10.    for i := 1 to 1 do begin
  11.       fff := TFilestream.create(filename, fmOpenRead or fmShareDenyWrite); //still read only.
  12.  
  13.       //write filestream to memorystream  
  14.            cache[0] := TMemorystream.create;  
  15.            cache[0].write(fff,fff.size);
  16.  
  17.       //write memorystream back to filestream
  18.       //fff.write(cache[0],cache[0].size); // no stop trying to write on a read only stream. Why would you want to?
  19.      
  20.       Image1.Picture.LoadFromStream(Cache[0]); //that is the way to go for a cached read.
  21.    end;
  22. end;
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Array of TMemorystream
« Reply #5 on: November 20, 2017, 04:28:00 pm »
@taazz: give the noobs something to do:

"There are more things in heaven and earth, Horatio,
Than are dreamt of in your philosophy.
- Hamlet (1.5.167-8), Hamlet to Horatio"

Don't give them a straight answer.  ::)
Specialize a type, not a var.

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #6 on: November 20, 2017, 04:35:49 pm »
THANKS!!!

setLength();  that was the clou!  I always forget about that!!!
the other sugestions I will check gladly.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Array of TMemorystream
« Reply #7 on: November 20, 2017, 04:44:50 pm »
@taazz: give the noobs something to do:

"There are more things in heaven and earth, Horatio,
Than are dreamt of in your philosophy.
- Hamlet (1.5.167-8), Hamlet to Horatio"

Don't give them a straight answer.  ::)
:-[
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #8 on: November 20, 2017, 04:45:34 pm »
@taazz

Quote
//fff.write(cache[0],cache[0].size); // no stop trying to write on a read only stream. Why would you want to?

I did that as i realized that Image1.Picture.LoadFromStream is expecting a Tfilestream. At least in my very first version. I have an eye on that as I dont like it like this myself. Now my array is working.

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #9 on: November 20, 2017, 06:00:12 pm »
@taazz
is is as I wrorte... I get an error reading my array directly...

Code: Pascal  [Select][+][-]
  1.     setlength(cache,1);
  2.         fff := TFilestream.create(StringGrid1.Cells[6,i], fmOpenRead or fmShareDenyWrite);
  3.     //write filestream to memorystream
  4.          cache[0] := TMemorystream.create;
  5.          cache[0].write(fff,fff.size);
  6.  
  7.     //write memorystream back to filestream
  8.     fff.write(cache[0],cache[0].size);
  9.  
  10.     Image1.Picture.LoadFromStream(cache[0]); //thats causing a stream read error
  11.     Image1.Picture.LoadFromStream(fff); //thats working here but probably not in the context I plan  
« Last Edit: November 20, 2017, 06:28:01 pm by ratmalwer »

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #10 on: November 20, 2017, 06:51:56 pm »
Last but not least... when its finished it looks so easy  :)

Code: Pascal  [Select][+][-]
  1. Cache: array of TFilestream;
  2. fff: TFilestream;
  3. .....
  4. begin
  5.   for i := 1 to 2 do begin
  6.     setlength(cache,i+1);
  7.     fff := TFilestream.create(StringGrid1.Cells[6,i], fmOpenRead or fmShareDenyWrite);
  8.     cache[i] := fff;
  9.     Image1.Picture.LoadFromStream(Cache[i]);
  10.     fff.free;
  11.  end;

ratmalwer

  • Jr. Member
  • **
  • Posts: 57
Re: Array of TMemorystream
« Reply #11 on: November 20, 2017, 08:28:54 pm »
It was not that easy... meanwhile i have this witch works with the current pictures in my loop. But when I call the first picture at the end with the same command LoadFromStream(cache[1]) my app crashes...

Code: Pascal  [Select][+][-]
  1. begin
  2.   for i := 1 to StringGrid1.Rowcount -1 do begin   //reads 3 Files
  3.     extension := ExtractFileExt(StringGrid1.Cells[6,i]);
  4.     if ((Uppercase(extension) = '.JPG') or (Uppercase(extension) = '.JPEG')) then begin
  5.       try
  6.        setlength(cache,i+1);
  7.        mmm := Tmemorystream.create;
  8.            mmm.LoadFromFile(StringGrid1.Cells[6,i]);
  9.        cache[i] := mmm;
  10.        Image1.Picture.LoadFromStream(Cache[i]);   //displays current file correct
  11.       finally
  12.         mmm.free;
  13.       end;
  14.        showmessage(inttostr(i));
  15.     end;
  16.  end;
  17.  showmessage(inttostr(i));
  18.  Image1.Picture.LoadFromStream(Cache[1]);  //should display first file but crashes ?????
  19. end;    

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Array of TMemorystream
« Reply #12 on: November 20, 2017, 09:34:53 pm »
But when I call the first picture at the end with the same command LoadFromStream(cache[1]) my app crashes...
You really should learn to set rangechecking, add debug etc so that you are able to produce something more meaningful then the words "my application crashes". Those words mean nothing and from that you are also not able to learn anything.

Code: [Select]
...
   mmm := Tmemorystream.create;
   mmm.LoadFromFile(StringGrid1.Cells[6,i]);
   cache[i] := mmm;
...
   mmm.free;
...
   Image1.Picture.LoadFromStream(Cache[1]);  //should display first file but crashes ?????

Are you able to tell us what the statement:
Code: [Select]
cache[i] := mmm; actually does ? Keep in mind that you are referring to classes.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Array of TMemorystream
« Reply #13 on: November 20, 2017, 09:36:28 pm »
Your app creashes because you have a try..finally construct in which you Free the memorystream cache immediately after creating and loading it.
Don't free the memorystream there - you haven't even used it yet.

You do need to destroy the memory streams you create, but not until the end of your program. Before that you will want to access those streams!
So include an OnDestroy handler for your form something like
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormDestroy(Sender: TObject);
  2. var
  3.   ms: TMemoryStream;
  4. begin
  5.   for ms in cache do
  6.     ms.Free;
  7. end;

Assume your image filenames were in an array (slightly less complicated than a grid). Then you want a FillCache() routine something like
Code: Pascal  [Select][+][-]
  1. SetLength(cache, ImageCount);
  2. for i:=1 to ImageCount do begin
  3.   cache[i-1]:=TMemoryStream.Create;
  4.   cache[i-1].LoadFromFile(PictureFileNames[i]);
  5. end;

Remember that your cache is indexed from 0 to ImageCount-1, and for you, ImageCount is StringGrid1.RowCount-1.
 
« Last Edit: November 20, 2017, 09:44:18 pm by howardpc »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Array of TMemorystream
« Reply #14 on: November 20, 2017, 09:45:43 pm »
Remember that your cache is indexed from 0 to ImageCount-1, and for you, ImageCount is StringGrid1.RowCount-2.
Are you sure about that howardpc ? because,
Code: [Select]
if ((Uppercase(extension) = '.JPG') or (Uppercase(extension) = '.JPEG')) then
Seems to indicate there is no relation whatsoever between rowcount and array index.

edit: although i agree that there is many more things wrong with code presented by TS, i think that TS believes that he made a copy instead of using a reference.
« Last Edit: November 20, 2017, 09:50:08 pm by molly »

 

TinyPortal © 2005-2018