Recent

Author Topic: How to load the content of a text file in a String Constant in compile time?  (Read 10316 times)

carlejt

  • New Member
  • *
  • Posts: 39
Hello,

I use lazarus 1.6-win32.

How to load the content of a text file in a String Constant in compile time?

The text file varies so much, and i want when I click compile the compiler take the contents of this text file and store it in a string constant. It is possible ?, there a solution?

Thanks for the attention.




engkin

  • Hero Member
  • *****
  • Posts: 3112
Code: Pascal  [Select][+][-]
  1. {$codepage UTF8}
  2. const
  3.   cStr = {$I file.txt};

carlejt

  • New Member
  • *
  • Posts: 39
Thanks for answering,

file.txt(1,7) Fatal: illegal character "'"'" ($22)

but I do not work me, it is that what I have in the text file is not a pascal code.

engkin

  • Hero Member
  • *****
  • Posts: 3112
It has to be a pascal constant. The compiler is going to include that file as is. For instance, if you want to make that constant equal to abc then the text file should be:
Quote
'abc'

Maybe if you explain why you need it there might be a better solution.

carlejt

  • New Member
  • *
  • Posts: 39
Well, in the text file there is a script, which i want to not be visible, but this script varies so much, so i need to automate the compilation process.

eny

  • Hero Member
  • *****
  • Posts: 1634
You could try adding the textfile as a resource (I always do that for external content or config data that changes frequently).
Only caveat is that when you change a resource, you need to make a change to the source that includes it (e.g. add an extra whiteline or delete it).
Or else the build process will not notice the change.
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

molly

  • Hero Member
  • *****
  • Posts: 2330
... you need to make a change to the source that includes it (e.g. add an extra whiteline or delete it).
Or else the build process will not notice the change.
Only if you use the 'old' method of including resources. In fact, the behaviour you seem to describe , stems from 'simpy' using include files (which suffer from not being build into when source not changed)

If you use a 'real' resource (when possible, it could be not all platforms support it), then you could load the script using resource specific functions for it. e.g. load the text into string at startup of your program (or when needed).

PS: I can't imagine any such texts to be required at compile time. In fact almost nothing requires to be 'active' at compile time, unless you need to modify compilation behaviour (such as by including environment variables or decide whether one piece of code requires to be compiled or not, using ifdefs).
« Last Edit: May 23, 2016, 09:38:17 pm by molly »

carlejt

  • New Member
  • *
  • Posts: 39
I solved the old way, thanks very much to everyone for all the attention and guidance.

Always very grateful to this forum.

eny

  • Hero Member
  • *****
  • Posts: 1634
... you need to make a change to the source that includes it (e.g. add an extra whiteline or delete it).
Or else the build process will not notice the change.
Only if you use the 'old' method of including resources. In fact, the behaviour you seem to describe , stems from 'simpy' using include files (which suffer from not being build into when source not changed)

If you use a 'real' resource (when possible, it could be not all platforms support it), then you could load the script using resource specific functions for it. e.g. load the text into string at startup of your program (or when needed).
Nope, using actual resources, not include files.
And the build process does not (and never has) detect resource changes.
Hence the extra step to convince the compiler to also reload the resource after a change.
http://wiki.lazarus.freepascal.org/Lazarus_Resources#FPC_resources
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

molly

  • Hero Member
  • *****
  • Posts: 2330
...
And the build process does not (and never has) detect resource changes.
...
That is really strange that you experience such behaviour as i myself certainly haven't.

I add the resource using lazarus project options and load it _once_ manually. Each time a change is made inside the original file, it is automatically included into the resource for me when i compile the project. E.g. no need to modify anything for me but the original file on disk that is part of the project as resource.

Platform related differences maybe ? I just checked on windows to make sure.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
You could try adding the textfile as a resource (I always do that for external content or config data that changes frequently).
Only caveat is that when you change a resource, you need to make a change to the source that includes it (e.g. add an extra whiteline or delete it).
Or else the build process will not notice the change.
Well, that is cumbersome..Not wrong, it works, but:
The correct way to force a full rebuild is specify -B as command-line parameter.

On subject itself: yes, you better include the text file as a resource.
The other option is to preprocess the file to Pascallify it (escape quotes etc) before you do the suggested
string = {$I text.txt}.
That's basically a about one/two/three line utility program.

Here's one using KOL:
Code: Pascal  [Select][+][-]
  1. program Pascallify;
  2. {$IFDEF FPC}{$MODE DELPHI}{$H+}{$IFNDEF WINDOWS}{$ERROR this code is windows only!}{$ENDIF}{$ENDIF}
  3. {$APPTYPE CONSOLE}
  4. uses
  5.   kol;
  6. var
  7.   S:string;
  8. begin
  9.   S:= StrLoadFromFile(Paramstr(1)); //assume first parameter on the commandline as input file
  10.   S:=String2PascalStrExpr(S); // Basically, this is what makes it work as an include file to assign.
  11.   StrSaveToFile(Paramstr(2),S); // Assume second parameter as output file
  12. end.
  13.  

Of course you should build in some checks ;) But this is the logic and it works.

The one liner is this, for the horrifying code competition:
Code: Pascal  [Select][+][-]
  1. program Pascallify;
  2. {$IFDEF FPC}{$MODE DELPHI}{$H+}{$ENDIF}{$APPTYPE CONSOLE}
  3. uses kol;
  4. begin
  5.   StrSaveToFile(ParamStr(2),String2PascalStrExpr(StrLoadFromFile(Paramstr(1))));
  6. end.
  7.  

Compile as: ppc386 -dNOT_USE_RICHEDIT -Rintel -Mdelphi -dVER2 pascallify.dpr

I attached a 7zip binary.
Usage: "Pascallify <input.txt> <output.txt>"
The output can be included as a pascal string usable for internal processing.
NO checks are done! It's the compiled one-liner, with UPX applied. Limit is a 2GB Ansi string file.
« Last Edit: May 25, 2016, 12:00:06 pm by Thaddy »
Specialize a type, not a var.

eny

  • Hero Member
  • *****
  • Posts: 1634
...
And the build process does not (and never has) detect resource changes.
...
That is really strange that you experience such behaviour as i myself certainly haven't.
That is because you didn't test with an actual resource script (*.rc file; see the link about FPC resources).

Quote
I add the resource using lazarus project options and load it _once_ manually. Each time a change is made inside the original file, it is automatically included into the resource for me when i compile the project. E.g. no need to modify anything for me but the original file on disk that is part of the project as resource.
That sounds like a useful hidden gem  :D
Gonna test it tomorrow and add something to the Wiki if it works as advertised.

@Thaddy: very cumbersome indeed.
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

BeniBela

  • Hero Member
  • *****
  • Posts: 905
    • homepage
Is there a way to compress strings, so large text files do not waste mich space?

molly

  • Hero Member
  • *****
  • Posts: 2330
That is because you didn't test with an actual resource script (*.rc file; see the link about FPC resources).
Are you 100% sure about that ?  :P

Code: [Select]
> "D:\Windows\Applications\Development\FPC\3.0.0\bin\i386-win32\fpc.exe" -B -gl -FU"lib/$FPCTARGET" H:\molly\lazarus-dev-forums\resources_topic2_fpc\TestResource.pas
Free Pascal Compiler version 3.0.0 [2015/11/16] for i386
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling G:\molly\lazarus-dev-forums\resources_topic2_fpc\TestResource.pas
Compiling resource G:\molly\lazarus-dev-forums\resources_topic2_fpc\MyResources.rc
Compiling resource lib\i386-win32\TestResource.or
Linking G:\molly\lazarus-dev-forums\resources_topic2_fpc\TestResource.exe
38 lines compiled, 0.9 sec, 137904 bytes code, 4980 bytes data

> Process Exit Code: 0
> Time Taken: 00:01

And in case you doubt/ask: Also here i only have to change the contents of the .txt file. If necessary/wanted/helps i'll attach the whole project.

Quote
That sounds like a useful hidden gem
It actually is  :)

No idea why it isn't mentioned explicitly on that page you linked to as it makes things a lot easier.

One note though: i tested with older Lazarus version (might be the behaviour is still there), which has the annoyance that the resource file isn't included in the project _unless_ another option for the project was changed (e.g. the asterisk that shows that the project options were changed and can be saved).

In case you don't want to (or can't) include windows unit for RC_xxx definitions: you can use unit resources or, figure out the numbers from the windows unit (fpc resources advertises itself as being compatible). Can't remember, but i got some issues with that so i needed to use cast PChar(10) for representing RT_RCDATA.

Hopefully enjoy !  :)

eny

  • Hero Member
  • *****
  • Posts: 1634
That is because you didn't test with an actual resource script (*.rc file; see the link about FPC resources).
Are you 100% sure about that ?  :P
I'm 100% pure the problem exists.
Seems you do a full rebuild every time (-B option); that forces the compiler to also recompile the resource script and in that specific situation you will not 'experience the behaviour'.
I use the Lazarus IDE exclusively and when you enable the option to only rebuild changed modules (don't remember if it is on by default), it does not recognize changes in resources that are mentioned in a *.rc script. This is a bug but in the build process.

Quote
One note though: i tested with older Lazarus version (might be the behaviour is still there), which has the annoyance that the resource file isn't included in the project _unless_ another option for the project was changed (e.g. the asterisk that shows that the project options were changed and can be saved).
I indeed vaguely remember some problem with the resources.
But I'll definitely give it another try tomorrow because it looks like a nice feature.
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

 

TinyPortal © 2005-2018