Leaderboard
Popular Content
Showing content with the highest reputation on 09/10/20 in Posts
-
What is wrong with TStringList
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
You can do something similar using TStreamReader and its ReadLine() method, eg: var Stream := TReadOnlyCachedFileStream.Create('c:\temp\t'); try var Reader := TStreamReader.Create(Stream); try while not Reader.EndOfStream do begin S := Reader.ReadLine; // use S as needed... end; finally Reader.Free; end; finally Stream.Free; end; -
The most common way do text-processing in Delphi is to load a file into a TStringList and then process the text line-by-line. Often you need to save the contents of the StringList back to the file. The TStringList is one of the most widely used RTL classes. However there are a number of limitations discussed below: a) No easy way to preserve line breaks on Load/Save TStringList does not make any effort to recognize the type of line breaks (LF, CR or CRLF) in the files it opens, let alone save that for use on saving. b) Information loss without any warning or any option for dealing with that. Internally TStringList uses unicode strings, but when you save its contents to a file using the default encoding (ANSI), this may result in information loss, without getting any warning or having any means for dealing with that. TEncoding.GetBytes also suffers from that. c) No easy way to determine whether a file you loaded into a TStringList contained a BOM When you load a file (LoadFromFile method), the encoding of the file is stored but not the information about whether the file contained a BOM or not. The WriteBOM property is only used when you save a file. d) Last but not least, no easy way of dealing with utf8 encoded files without a BOM The default text file format in Linux systems, in Visual Studio Code and other editors, as well as in languages such as python 3 is utf8 without BOM. Reading such files with TStringList is problematic and can result in errors, because it thinks such files are ANSI encoded. You could change the DefaultEncoding to utf8, but then you get errors when you read ansi files. No effort is made to detect whether a file without a BOM contains utf8 sequences. Overall, it is desirable that, when you load a file using LoadFromFile and then you save it using SavetoFile, the saved copy is identical to the original. I am attaching a general purpose TStringList descendent that deals with all the above issues in case anyone has a use for that. XStringList.pas
-
What is wrong with TStringList
Remy Lebeau replied to pyscripter's topic in RTL and Delphi Object Pascal
It is worse than that. It loads the entire file into a local byte array, then it decodes the entire byte array into a single Unicode string, and then it parses that string to extract the lines into individual substrings. So, by the time the TStringList has finished being populated, and before TStrings.LoadFrom...() actually exits, you could be using upwards of 4-5 times the original file size in memory! Granted, this is temporary, and all of that memory gets freed when LoadFrom...() finally exits. But there is small window where you have a LOT of memory allocated at one time. -
What is wrong with TStringList
Stefan Glienke replied to pyscripter's topic in RTL and Delphi Object Pascal
Loading an entire file into a TStringList is a bad way to begin with tbh yet often the most easy way because there are no nice to use alternatives out of the box. -
What is wrong with TStringList
pyscripter replied to pyscripter's topic in RTL and Delphi Object Pascal
Agree. In the old days (pre Unicode) I wrote the attached Strmtxt.pas (converts a stream to a text file). It would need to be updated to work with recent versions of Delphi. And it works great with buffered streams such as @David Heffernan's TReadOnlyCachedFileStream. With that you could do something like: var Stream := TReadOnlyCachedFileStream.Create('c:\temp\t'); AssignStream(Txt, Stream); while not EOF(Txt) do begin Readln(Txt,S); Writeln(MemoText, S); end; However when you build a text editor such as SynEdit, you typically load the whole file in memory. In any case, the focus of this topic was the limitations of TStringList with regards to dealing with encodings, BOM and Line breaks. It was not about what is the most efficient way to do text processing in Delphi. STRMTXT.PAS -
Generics: Classes vs Records - Differences in use
David Heffernan replied to Lars Fosdal's topic in Algorithms, Data Structures and Class Design
We don't need a topic or any examples. We all know that records can be used as generic types. -
Should Exit be used instead of 'record Exists?' boolean?
Fr0sT.Brutal replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
As for me, everywhere I need search in arrays, I use generic classes or wrappers. Of course, if I have an array and need finding an item in just one place, I don't implement separate functions @dummzeuch, @Remy Lebeau good point though I prefer separating the methods -
Should Exit be used instead of 'record Exists?' boolean?
Remy Lebeau replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
In cases where I need the index of a found item, I prefer to have my Find* functions accept an optional parameter to output the index. That way, I can still return a pointer to the actual data and not have to re-index back into the data storage after Find* exits, but I can still use the index for other things as needed. For example: function FindRecord(aID: Integer; vIndex: PInteger = nil): PDataRec; var i: Integer; begin Result := nil; if vIndex <> nil then vIndex^ := -1; for i := Low(Data) to High(Data) do begin if Data[i].DataID = aID then begin Result := @Data[i]; if vIndex <> nil then vIndex^ := i; Exit; end; end; end; Or: function FindRecord(aID: Integer; var vIndex: Integer): PDataRec; overload; var i: Integer; begin Result := nil; vIndex := -1; for i := Low(Data) to High(Data) do begin if Data[i].DataID = aID then begin Result := @Data[i]; vIndex := i; Exit; end; end; end; function FindRecord(aID: Integer): PDataRec; overload; var ignore: Integer; begin Result := FindRecord(aProjectID, aID, ignore); end; -
Interposer classes are only good for components/controls that you already placed on forms because you can keep using them as is while you would need to replace a lets say TButton with TMyAwesomeButton. Where I also like to use them is for extending DUnit as I can use my unit with the TTestCase class then instead of the DUnit one and add functionality - but I would stay away from using it on RTL classes. Funny story: just yesterday we had a sudden compile error from a unit that was not touched in months. A class that was implementing an interface and the compiler complained about missing 2 method implementations. Turned out it was caused by the fact that a junior had added a TAction interposer class into a form unit. That unit was used in the unit which now failed - because those interface methods had TAction in their signature and now they did not match anymore.
-
Should Exit be used instead of 'record Exists?' boolean?
dummzeuch replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
Regarding Find-methods: I always make them return a boolean. If I need the index too, I make that an additional out parameter. If it gets too much hassle to always pass a dummy variable, I overload that method with one that does it for me and declare it inline: function TBla.Find(const _Key: TSomeType; out _Data: TSomeOtherType): Boolean; overload; inline; var Idx: Integer; begin Result := Find(_Key, _Data, Idx); end; -
[Android][CameraComponent] How do I get a sharp image with Autofocus or other?
flydev replied to Fabian1648's topic in FMX
For reference, I managed last year to get the "autofocus" working on Android. You can check it on my repo there : - https://github.com/flydev-fr/ZXing.Delphi.Demo - https://github.com/flydev-fr/ZXing.Delphi.Demo/blob/master/AdvancedTestApp/uMain.pas#L487-L515 -
What is wrong with TStringList
FPiette replied to pyscripter's topic in RTL and Delphi Object Pascal
That looks easy at first. You've found yourself there are limitations. But you forgot one important: using a TStringList load the full file into memory. This is probably not desirable if you want to support arbitrary large files. As previous answers mentioned, there are other possibilities. The best solution depends on what you intent to do. Sometimes it is easy to use memory mapped file. -
As I wrote it never stores a double - SQLite3 doesn't support TDateTime double which is Ole/Windows specific. In your code, text will be stored. It is because that SQliteStudio display what is stored, i.e. text, trying several date/time layouts. It seems that FireDac expects ISO-8601 encoding - just as SQLite3. And don't forget to set the seconds - even :00.
-
Issues Deploying Firebird DB on Ubuntu 8.04LTS
Larry Hengen replied to Larry Hengen's topic in Cross-platform
I reported this as RSP-30899 and posted on the Firebird support forums as well asking for a workaround. -
Should Exit be used instead of 'record Exists?' boolean?
FPiette replied to Mike Torrettinni's topic in Algorithms, Data Structures and Class Design
I always use the Exit method. -
Disabling Welcome Page is on my check list for Delphi installation 🙂
-
August 2020 GM Blog post
pyscripter replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
It refers to the intention to promote Python4Delphi as a means of bringing Python and Delphi closer together: Python for Delphi (P4D) is a set of free components that wrap up the Python dll into Delphi and Lazarus (FPC). They let you easily execute Python scripts, create new Python modules and new Python types. You can create Python extensions as dlls and much more. P4D provides different levels of functionality: Low-level access to the python API High-level bi-directional interaction with Python Access to Python objects using Delphi custom variants (VarPyth.pas) Wrapping of Delphi objects for use in python scripts using RTTI (WrapDelphi.pas) Creating python extension modules with Delphi classes and functions P4D makes it very easy to use python as a scripting language for Delphi applications. It comes with an extensive range of demos and tutorials. -
August 2020 GM Blog post
Lars Fosdal replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
A forum is a place for reasoning and discussion. SO, not so much. What do you prefer? I guess most people go to SO to get an answer, provided one exists, and if not - use a forum. Edit: I gave up on SO for asking questions a long time ago. -
August 2020 GM Blog post
Lars Fosdal replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
But SO is not a forum. Questions that are ... unprecise ... get eradicated fast and hard. -
August 2020 GM Blog post
Dalija Prasnikar replied to Darian Miller's topic in Tips / Blogs / Tutorials / Videos
Not really... official forums were already dead. They basically died when NNTP was dropped.