Recent

Author Topic: MultiFormat File - Simplest - Flexible  (Read 24535 times)

pixelink

  • Hero Member
  • *****
  • Posts: 1269
MultiFormat File - Simplest - Flexible
« on: August 22, 2016, 08:35:25 pm »
If anyone has seen some recent threads I made on IDE/CreateEXE or Resource Files...
I have a working prototype of an IDE that can write (Writer.exe) a stream of data (just basic string for now) directly into a 2nd EXE (Reader.exe).. it appends the data to the end of the exe.... It works beautifully!

And FYI... This is not Fungus code... I have something else that is more inline with my goals.

NOTE: I am not making anything in particular, just doing a prototype to make sure I can read/write most formats into one file.
I build prototypes when learning stuff.

Now I am building the stream (string) that will be appended to the exe.
However, after I started coding I realized some things that could go wrong...

My data file can have these formats saved into it...

- bmp, jpg, png
- Icons
- Text
- Rtf

Each format may be different lengths
And I would be loading binary into controls, so conversion will be needed from the string
My file needs to be easy to write and read for flexibility sake.

Writing the data to the file is fine using just old-school saving. I am saving into a TXT file
This is a sample file...

Code: Pascal  [Select][+][-]
  1. This is a plain line text string
  2. This is the 2nd plain line text string
  3. 500
  4. This is the beginning of a Memo String
  5.  
  6. That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text That has a line break and paragraph text

The 500 is the length of my Memo string.
I actually saved it in the file so I don't have to parse the data to figure it out.

However, when it comes to the block of text that has line breaks, I can't use ReadLn

So, I am trying to read an entire block.
I am keeping track of the Pos and length as i move through the file.

So, While the file is open, what is the Pascal way of getting block of string (using Length)??

Here is the code I am using to read the file...

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button3Click(Sender: TObject);
  2. var
  3.   Pos: Single;
  4.   StrLength: Single;
  5.   X: String;
  6. begin
  7. Pos:= 0;
  8. AssignFile(tfIn, fileName);
  9. try
  10.   // Open the file for reading
  11.   reset(tfIn);
  12.  
  13.   //edit box
  14.   readln(tfIn, s);
  15.   Pos:= Length(s);
  16.   Edit1.Text := s;
  17.  
  18.   readln(tfIn, s);
  19.   Pos:= Pos + Length(s);
  20.   Edit2.Text := s
  21.  
  22.   //Memo
  23.   //get str length for memo block
  24.   StrLength:= Length(s);
  25.  
  26.   X:=SubStr(readln(tfIn, S,Pos,StrLength));
  27.   RichMemo1.Text := X;
  28.   Pos:= Pos + StrLength;
  29.  
  30. // Done so close the file
  31.   CloseFile(tfIn);
  32.  
  33. except
  34.   on E: EInOutError do
  35. end;
  36. end;  
  37.  

WHAT IS THE BEST... way to go about this?
« Last Edit: August 22, 2016, 08:37:28 pm by technipixel »
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

Fungus

  • Sr. Member
  • ****
  • Posts: 354
Re: MultiFormat File - Simplest - Flexible
« Reply #1 on: August 22, 2016, 08:41:34 pm »
You should use TFileStream for file I/O and then you could use these babies:

Code: Pascal  [Select][+][-]
  1. Procedure StringToStream(Const Stream: TStream; Const Str: String);
  2. Var C: Cardinal;
  3. Begin
  4.   C:= Length(Str);
  5.   Stream.Write(C, SizeOf(C));
  6.   Stream.Write(Str[1], C);
  7. End;
  8.  
  9. Function StringFromStream(Const Stream: TStream): String;
  10. Var C: Cardinal;
  11. Begin
  12.   Stream.Read(C, SIzeOf(C));
  13.   SetLength(Result, C);
  14.   Stream.Read(Result[1], C);
  15. End;

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #2 on: August 22, 2016, 08:57:48 pm »
I thought about that!!
But, was thinking more on the lines of ReadLn because I will have more one line settings then blocks.

But, I will check it out.

So, in the Docs, the wiki suggest that we don't use Cardinal, but unit NativeUnit
http://wiki.freepascal.org/Cardinal

Any reasoning why you don't don't... just trying know the Pascal Lang
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #3 on: August 22, 2016, 09:06:40 pm »
@FUNGUS,

By the way... Your code worked fine, but it saved the data in a copy of the EXE that wrote the data.
So, Any controls I put on the "IDE" also showed up on the 2nd "combined" exe.

I did find a Delphic example that I had to port into LAZ that had a separte EXE that looked one way and the 2nd that look another.
Same idea though. I was able to tweak the code to get it to work.

Also, just for my learning... Every time I messed around with your code and it generated an error (user coding error)   :-[
It would crash the memory stack and I would ge this crazy GBD.exe dialog.

The only way to stop that window was to reboot... I actually posted a thread on it.

Is TMemoryStream that sensitive to corrupting the stack??
It's just weird... never saw that in .NET

THANKS FOR ALL YOUR HELP
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: MultiFormat File - Simplest - Flexible
« Reply #4 on: August 22, 2016, 09:18:01 pm »
So, in the Docs, the wiki suggest that we don't use Cardinal, but unit NativeUnit
http://wiki.freepascal.org/Cardinal

Any reasoning why you don't don't... just trying know the Pascal Lang

The wiki (correctly) suggests not to use Cardinal for memory/pointer/address references and pointer arithmetic, as was widely seen in 32-bit Delphi code 10 years ago (before 64-bit processors and operating systems became widespread).
It does not suggest that you don't use cardinal (=DWord) at all. Cardinal is a useful, and widely used, Pascal type. It's not about to be deprecated! It's just that in a 64-bit world it is now unsuitable to use in conjunction with pointers, or for memory addressing.
« Last Edit: August 22, 2016, 09:19:47 pm by howardpc »

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #5 on: August 22, 2016, 09:28:58 pm »
So, in the Docs, the wiki suggest that we don't use Cardinal, but unit NativeUnit
http://wiki.freepascal.org/Cardinal

Any reasoning why you don't don't... just trying know the Pascal Lang

The wiki (correctly) suggests not to use Cardinal for memory/pointer/address references and pointer arithmetic, as was widely seen in 32-bit Delphi code 10 years ago (before 64-bit processors and operating systems became widespread).
It does not suggest that you don't use cardinal (=DWord) at all. Cardinal is a useful, and widely used, Pascal type. It's not about to be deprecated! It's just that in a 64-bit world it is now unsuitable to use in conjunction with pointers, or for memory addressing.

Could that explain why I have been getting memory corrupted stacks when the app crashed?
The "Cardinal" was in the code I was using yesterday.
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #6 on: August 22, 2016, 09:35:25 pm »
Back to my file...

When using Utf8ToAnsi on a FileStream....
Am I going to have problems loading Normal text and RTF coded text while the same Stream is opened?

My file will have both normal string and encoded string.
Can I work with both with one stream?
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: MultiFormat File - Simplest - Flexible
« Reply #7 on: August 22, 2016, 10:49:18 pm »
Could that explain why I have been getting memory corrupted stacks when the app crashed?

One can't usually guess what causes a crash (unless it is obvious you've done something like dereferencing a nil pointer). The only way is to trace through the code to debug it. If you're still getting crashes, you can share your code if you want other eyes to help debug it. But that needs all the compilable code (not just a snippet).

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #8 on: August 23, 2016, 12:04:25 am »
You should use TFileStream for file I/O and then you could use these babies:

Function StringFromStream(Const Stream: TStream): String;
Var C: Cardinal;
Begin
  Stream.Read(C, SIzeOf(C));
  SetLength(Result, C);
  Stream.Read(Result[1], C);
End;[/code]

For the life of Me, I can't figure out why the code below is not working
Code: Pascal  [Select][+][-]
  1.  
  2. fs: TFileStream;
  3. procedure TForm1.Button2Click(Sender: TObject);
  4. Var C: Cardinal;
  5.     Result:String;
  6. begin
  7.  
  8.   fs := TFileStream.Create('test.txt', fmOpenRead);
  9.    fs.Read(C, SIzeOf(C));
  10.   SetLength(Result, C);
  11.   fs.Read(Result[1], C);
  12.   Memo1.Text :=AnsiString(fs);
  13.   fs.Free;
  14.  
  15. end;
  16.  

It is suppose to return a file full of normal text and RTF text
But it returns.... "?UT"
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4631
  • I like bugs.
Re: MultiFormat File - Simplest - Flexible
« Reply #9 on: August 23, 2016, 12:13:49 am »
  Memo1.Text :=AnsiString(fs);
That makes no sense.
Mostly Lazarus trunk and FPC 3.2 on Manjaro Linux 64-bit.

sky_khan

  • Guest
Re: MultiFormat File - Simplest - Flexible
« Reply #10 on: August 23, 2016, 12:19:57 am »
Beauty of procedures is that they can be reusable.

try this
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   fs : TFileStream;
  4. begin
  5.   fs := TFileStream.Create('test.txt', fmOpenRead);
  6.   try
  7.     Memo1.Lines.Text :=StringFromStream(fs);
  8.   finally
  9.     fs.free;
  10.   end;
  11. end;
  12.  

Phil

  • Hero Member
  • *****
  • Posts: 2737
Re: MultiFormat File - Simplest - Flexible
« Reply #11 on: August 23, 2016, 12:21:06 am »
  Memo1.Text :=AnsiString(fs);
That makes no sense.

Agreed.

Since you read C bytes into Result, try this:

Memo1.Text := Result;

Tip: Don't name your variable Result, since that's the name to use when returning a function result.

And put fs declaration inside your event handler. Don't see any reason why it's outside.

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #12 on: August 23, 2016, 12:22:52 am »
  Memo1.Text :=AnsiString(fs);
That makes no sense.

If I don't have it, it generate an error saying it expects AnsiString
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

sky_khan

  • Guest
Re: MultiFormat File - Simplest - Flexible
« Reply #13 on: August 23, 2016, 12:26:50 am »
"ansistring(fs)" is (forced) typecasting.  You are telling compiler "recognize fs as ansistring" but its not!
So typecasting is a dangerous thing if you dont know what you are doing.

pixelink

  • Hero Member
  • *****
  • Posts: 1269
Re: MultiFormat File - Simplest - Flexible
« Reply #14 on: August 23, 2016, 12:28:14 am »
Beauty of procedures is that they can be reusable.

try this
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   fs : TFileStream;
  4. begin
  5.   fs := TFileStream.Create('test.txt', fmOpenRead);
  6.   try
  7.     Memo1.Lines.Text :=StringFromStream(fs);
  8.   finally
  9.     fs.free;
  10.   end;
  11. end;
  12.  
Error on this line...

Code: Pascal  [Select][+][-]
  1. Memo1.Lines.Text :=StringFromStream(fs);
  2.  

Identifier not found
Can't Type - Forgetful - Had Stroke = Forgive this old man!
LAZ 4.2.0 •  VSSTUDIO(.Net) 2022 • Win11 • 32G RAM • Nvida RTX 4070 Ti Super

 

TinyPortal © 2005-2018