Alright, I've solved my problem thanks to Bart's response
I'd like to give a bit more context in case someone else finds this issue as confusing as I did.
Task: Given two files, One UTF8 encoded and a second Ansi (Windows) encoded, add strings from the second to the first without changing its encoding type.
My problem was that after adding the strings and saving the second file, it would automatically revert to ANSI (windows) encoding. Incidentally, if someone is wondering how I can tell what the file encoding is, I use psPAd which indicates the encoding on its status bar.
All along I thought that Tstringlist.SaveToFile was the culprit, but thanks to Bart's answer, I realized that my error had been in copying from the ascii file without changing its content to UTF8.
Here is a bit of code that illustrates how to make this work. This code is didactic and for illustration purposes. Those who understand it already would find it a bit simplistic but that's its purpose. Please note that I am not adding anything to what Bart had told me in his reply; I'm rehashing it with a bit more details for those of us who are new to these concepts in Lazarus. Hopefully, this might help someone else to better understand what Bart wrote.
Function LoadUTF8File(const aFileName: String);
//Loads a utf8 encoded file. Please be sure the file is utf8 encoded
begin
Result := TStringList.Create; // TStringList by default expects a utf8 encoded file.
If FileExists(aFileName)
then Result.LoadFromFile(aFileName);
end;
Function LoadAsciiFile(const aFileName: String);
//Loads a windows native (code page ASCII (Windows)) file
begin
//Now this code is a bit counter-intuitive. If TstringList expects a utf8 encoded file
//wouldn't it mess things up if we were to give it an ascii file instead?
//Apparently not. For those of you who are coming from Delphi, I think it is a bit
//easier to understand why the Lazarus Team did not equip TStringList with an
//explicit LoadFromFile(const aFileName: String; const aCodeBase...) is because
//this situation of having to convert between UTF8 and Ascii is (I think) specific to
//Windows. It does not occur under linux. Having said that, please be aware that
//if you have to do this sort of transformation of a windows file under linux, my sample
//code here might not work
Result := TStringList.Create;
//We load the file as we did in the prior case...
If FileExists(aFileName)
then Result.LoadFromFile(aFileName);
//Now a bit of magic. Make sure though that FileUtil is in the use statement. If you
//are writing a console program, you need to add a package containing FileUtil, such
//as LCL. LCLBase might work to but I haven't tried it.
Result.Text := systoUTF8(Result.Text);
//What that previous line does is to convert a string from the system default code page,
//which in our case is ASCII Windows into UTF8. Now, FileUtil contains additional UTF8 methods
//that you might be interested in.
end;
//Now By opening the UTF8 and Ascii Windows file with these two methods, you achieve parity: they are both UTF8 encoded. You can then
//perform string manipulation by using Pos, PosEx, Copy etc to move the content of one file into another. Then to save the UTF8 encoded file, simply use TStringList.SaveToFile. This operation produces a UTF8 encoded file.