David Schwartz 426 Posted December 2, 2022 (edited) I have a situation where I've got a form that has a bunch of listboxes on it. I stuffed them full of (static) data and it was convenient to leave the data there. Now I want to move the logic into a formless unit. I saved the contents of these listboxes to flies. But in the end, I'd prefer not to have several files nor even one zip file that the app depends upon. A long time back there was a component whose name escapes me that was a sort of file store to save things like ini and txt files right on a datamodule so they were compiled into the program. In this case, there are about 15 txt files that I'd like to drop into such a component, perhaps inside of a zip file and save the zip file there (to save space). Any ideas on components or ways to accomplish that, other than saving them as a bunch of JSON or CSV text somewhere. BTW, they do get updated periodically, but very infrequently. I've actually been saving the data in TRzTabbedListbox components, and I open the IDE and edit the data in the property editor when I've needed to change anything. Edited December 2, 2022 by David Schwartz Share this post Link to post
aehimself 396 Posted December 2, 2022 We had a custom component which was only a wrapper for a TStringList, you can do something like this. On the other hand I feel like we are wasting memory; to store textual data you simply can use string constants or if you don't want to convert your TXT files into Delphi strings, build a .res file from them and embed it to the compiled application. In case you wish to convert, I have a method which seemed to work in simple cases and properly splits the input into 255-length chunks while preserving line breaks and escapes apostrophes: Function ToDelphiString(Const inString: String): String; Const ADDITION = #39' + '#39; BREAKAT = 80; Var line, a, max: Integer; sb: TStringBuilder; strarr: TArray<String>; Begin sb := TStringBuilder.Create; Try sb.Append(#39); strarr := AdjustLineBreaks(inString).Split([sLineBreak]); For line := Low(strarr) To High(strarr) Do Begin max := strarr[line].Length Div BREAKAT; For a := 0 To max Do Begin sb.Append(strarr[line].Substring(a * BREAKAT, BREAKAT).Replace(#39, #39#39)); sb.Append(#39); If a <> max Then sb.Append(' +' + sLineBreak + #39); End; If line <> High(strarr) Then sb.Append(' + sLineBreak +' + sLineBreak + #39); End; Result := sb.ToString; Finally FreeAndNil(sb); End; End; Share this post Link to post
Fr0sT.Brutal 900 Posted December 2, 2022 I chose resources way. You can edit a file with any editor and then just rebuild. 2 Share this post Link to post
Attila Kovacs 629 Posted December 2, 2022 (edited) I made this component back in the days, drop it on a form/datamodule, you can add files by doubleclicking the component on the form or manually enter text by adding items. Use it like: "Storage['Title']" I have commented out some encryption stuff but you can implement it yourself if you need it. It can zip its content. (Install it by creating a new package and add the units to it) Public domain, no restrictions, have fun. forsix.StringListHelper.pas forsix.VCL.Storage.pas forsix.VCL.Storage.Design.pas Edited December 2, 2022 by Attila Kovacs 1 Share this post Link to post
programmerdelphi2k 237 Posted December 2, 2022 (edited) my tip for "zip" your infos: memory or disk! many know about ZLib compress in Delphi usage, TCompressXXXX = ok! now add this: take your info in string format, like using Base64 convertion ( dont worry about size.... final-string = source + 1/3(source) --- dont worry, continue reading... after convert your string in Base64, convert it in "bytes" --- here the magic flowing... (many equal digits will be "the point" to elimate duplicates) after this, compress it using your ZLib class it's ready! you can get until "90% off" (or more) as result! I have tested with text, bitmap, and other types! bitmap 8MBytes stay with 1.x MBytes same that the type is already compress by default, like GIF, JPEG, etc.. you can reduce it more! there are no losses, because the real-data it's not affected! Edited December 2, 2022 by programmerdelphi2k Share this post Link to post
David Schwartz 426 Posted December 3, 2022 (edited) 17 hours ago, aehimself said: We had a custom component which was only a wrapper for a TStringList, you can do something like this. On the other hand I feel like we are wasting memory; to store textual data you simply can use string constants or if you don't want to convert your TXT files into Delphi strings, build a .res file from them and embed it to the compiled application. Sorry, I don't see what this is bringing to the party. I'm already opening the files and loading them into a stringlist. That's easy. What I want is to have the data actually embedded in the EXE somehow so I don't have to copy the text files around. Yes, I can put them all into a single zip file, but I still have to copy that zip file around with the EXE. It's the same problem as with DLLs. These are just some files containing text data saved from listboxes. And yes, I know I can declare them as resource strings. But that means when I update them (in another program) then I have to save them to disk as txt files and then go through a process of copying and pasting the data into the files with the resource strings. Either that or I need to write some code to take the contents of the list boxes and save them into .pas files that declare them as resource strings. That's certainly a solution, but I'd rather just be able drag and drop the txt files (or paste a filename) into a component on a form in the IDE and have them saved on the form for access at run-time. Edited December 3, 2022 by David Schwartz Share this post Link to post
David Schwartz 426 Posted December 3, 2022 11 hours ago, programmerdelphi2k said: my tip for "zip" your infos: memory or disk! again, I don't see what this is bringing to the party. It makes a zip file that's separate from the EXE, right? Share this post Link to post
programmerdelphi2k 237 Posted December 3, 2022 (edited) no no no... my "zip" is about "compressing and decrease the amount of data to be written to memory or disk" you talk about "zip... it", not me! 19 hours ago, David Schwartz said: In this case, there are about 15 txt files that I'd like to drop into such a component, perhaps inside of a zip file and save the zip file there (to save space). Edited December 3, 2022 by programmerdelphi2k Share this post Link to post
David Schwartz 426 Posted December 3, 2022 19 minutes ago, programmerdelphi2k said: no no no... my "zip" is about "compressing and decrease the amount of data to be written to memory or disk" Thanks, I know how to do this part. 🙂 the component in question allows you to take files and save them to the form so they're part of the application and don't need to be maintained separately. I'm looking for something similar. it looks like Atilla Kovacs posted something that's exactly what I'm looking for. I'm testing it now. Share this post Link to post
Pat Foley 51 Posted December 3, 2022 (edited) 1. Use meminifile.setstrings(default Strings to load program when external data not found) 2. The exe carries all the modes publish, editor, writer. The inifile and email of user loads the controls needs for that user. 3. The controls are bound when the program reads the "script". Bottom up or data driven loading. I used Expression parser by Egbert van Nes. 3 times easier than JS and CSS. Plus that pseudo business 4. The EventLeader waits for callbacks from remote API to update the UI. 5. Time Estimate TE 10 hrs. but building each form as exe and setting into app saves 1 hour per unit * 4. The eventLeader sheds its skin with a dot {.R *dfm} and classed as TwinControl was TForm. 1 hour plus 1 hr to write the script for each task's controls and interactions. Ability to adjust in the field without a recompile is worth a few hours. Scott Hanselman's blog might be a good source for info on running and setting web site. Edited December 3, 2022 by Pat Foley Cross out JS Share this post Link to post
David Schwartz 426 Posted December 3, 2022 18 hours ago, Attila Kovacs said: I made this component back in the days, drop it on a form/datamodule, you can add files by doubleclicking the component on the form or manually enter text by adding items. Use it like: "Storage['Title']" I have commented out some encryption stuff but you can implement it yourself if you need it. It can zip its content. (Install it by creating a new package and add the units to it) Public domain, no restrictions, have fun. forsix.StringListHelper.pas forsix.VCL.Storage.pas forsix.VCL.Storage.Design.pas That's EXACTLY what I was looking for, and it works perfectly! Thanks! Share this post Link to post
softtouch 9 Posted December 3, 2022 6 hours ago, David Schwartz said: That's EXACTLY what I was looking for, and it works perfectly! Thanks! Do you have by chance the component available? I am also looking for a form storage. Share this post Link to post
Attila Kovacs 629 Posted December 3, 2022 26 minutes ago, softtouch said: Do you have by chance the component available? I am also looking for a form storage. Just download the 3 units above and add it to a newly created package and save it and install it Share this post Link to post
softtouch 9 Posted December 3, 2022 26 minutes ago, Attila Kovacs said: Just download the 3 units above and add it to a newly created package and save it and install it All right. Does it allow to add binary files too or only text files? Share this post Link to post
Attila Kovacs 629 Posted December 3, 2022 1 minute ago, softtouch said: All right. Does it allow to add binary files too or only text files? It's for text only. I'd put binary in resources. Or you can extend the component to apply to your needs.. but in this case you have to replace tstringlists with streams and implement a Writer and a Reader for the dfm. 1 Share this post Link to post
David Schwartz 426 Posted December 3, 2022 8 hours ago, softtouch said: Do you have by chance the component available? I am also looking for a form storage. I have a general catch-all component library I use called AddOns that I put stuff like this into. You just need to be sure to change the name of the library in the call to Register so it ends up in that library with the others. It was very easy to do. Share this post Link to post
softtouch 9 Posted December 4, 2022 On 12/3/2022 at 8:54 PM, David Schwartz said: I have a general catch-all component library I use called AddOns that I put stuff like this into. You just need to be sure to change the name of the library in the call to Register so it ends up in that library with the others. It was very easy to do. I believe, the component you have been looking for was TmxStorage from maxcomponents. Share this post Link to post
David Schwartz 426 Posted December 5, 2022 6 hours ago, softtouch said: I believe, the component you have been looking for was TmxStorage from maxcomponents. Could be. It has been a long time since I looked at it. Share this post Link to post
Fr0sT.Brutal 900 Posted December 5, 2022 On 12/3/2022 at 5:20 AM, David Schwartz said: What I want is to have the data actually embedded in the EXE somehow so I don't have to copy the text files around. While you've found what you were looking for, I suspect you misunderstood "resource" approach. It's not about resourcestrings. It's just one .RC file with single line "StrRes RCData "StrRes.txt"" and one call to TResourceStream at runtime. Elementary but it has advantage of separating form definition from text data which is more convenient for version control 1 Share this post Link to post
David Schwartz 426 Posted December 5, 2022 14 hours ago, Fr0sT.Brutal said: While you've found what you were looking for, I suspect you misunderstood "resource" approach. It's not about resourcestrings. It's just one .RC file with single line "StrRes RCData "StrRes.txt"" and one call to TResourceStream at runtime. Elementary but it has advantage of separating form definition from text data which is more convenient for version control RIght, I'd forgotten about that. This data hasn't changed in years. The advantage I see of the on-board storage is it applies Zip compression to the data so it gets shrunk down by 80% or so. I guess I could do that by adding the files into a zip file first than putting that into the .rc file, but it's just an extra step for something that can easily get missed. (But the program won't work without these files, so ...) Also, the compression helps in obscuring the text in case anybody is casually looking at the binary data. But I appreciate the reminder. Share this post Link to post