-1

In my Delphi 10 Seattle app, I am reading a text file (actually an ini file) using TextFile as below:

    SDPath := ClientUtils.GetSharedPath;
    FileName := TPath.Combine(SDPath, 'Client.ini');
    if not MemoVisible then
    begin
      Panel2.Visible := True;
      if FileExists(FileName) then
      begin
        MemoConfig.Lines.Clear;
        AssignFile(T, FileName);
        try
          Reset(T);
          while not Eof(T) do
          begin
            ReadLn(T, text);
            MemoConfig.Lines.Add(text)
          end;
        finally
          CloseFile(T);
        end;
      end

I noticed that the first line contains [Configuration], 3 additional characters that weren't in the original file. I'm guessing this is from when the client.ini file was deployed from my Windows 7 PC. After I have edited the characters out and saved the file with

      AssignFile(T, FileName);
      try
        Rewrite(T);
        for i := 0 to MemoConfig.Lines.Count -1 do
          WriteLn(T, MemoConfig.Lines[i]);
      finally
         CloseFile(T)
      end;

the file remains correct. Where did the extra characters comes from and what can I do to prevent them from getting into the file?

Jerry Dodge
  • 26,858
  • 31
  • 155
  • 327
Freddie Bell
  • 2,186
  • 24
  • 43

2 Answers2

2

Those characters are a byte-order mark indicating that your file is encoded as UTF-8. The classic Delphi file-reading functions aren't aware of byte-order marks.

To prevent them from appearing in your file, consult the documentation for the program you used to create the file. You might have the option of excluding the mark explicitly, or you might be able to select a different encoding.

You might wish to avoid further use of the classic text-file functions. You could replace most of your code with a single function call:

MemoConfig.Lines.LoadFromFile(FileName);

That function also offers additional parameters to let you be explicit about what text encoding to use when reading the file. You should always know what text encoding you're using, especially with files that you're in control of like this one.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
1

Those characters are the Unicode UTF-8 byte order markers (EFBBBF hex).

You can prevent them from coming back by properly saving the file from whatever text editor you're using to create it. Save the file as ASCII or ANSI format text.

As far as your code, it's doing a lot more work than it should. You can load the file into your memo much more easily:

SDPath := ClientUtils.GetSharedPath;
FileName := TPath.Combine(SDPath, 'Client.ini');
if not MemoVisible then
begin
  Panel2.Visible := True;
  if FileExists(FileName) then
  begin
    MemoConfig.Lines.Clear;
    MemoConfig.Lines.LoadFormFile(FileName);
  end;
end;

Your code to save the file then becomes the converse:

MemoConfig.Lines.SaveToFile(FileName);
Ken White
  • 123,280
  • 14
  • 225
  • 444
  • I used Notepad on my Windows 7 PC to create the file originally. Then it is deployed to the Android using the deployment manager. Should I be using the overloaded version LoadFromFile(FileName, TEncoding.UTF8)? – Freddie Bell Apr 29 '16 at 18:59
  • Notepad's default should be ANSI encoding (at least it is on my machine), which does not contain byte order markers. If you create a new empty text file in Notepad, and then do a Save As, what encoding is listed at the bottom next to the Save button? – Ken White Apr 29 '16 at 19:49
  • And to answer your question, you shouldn't have to use the overloaded version; TStringList.LoadFromFile should detect the BOM automatically. Also, out of curiosity, if you're working with an INI file, why aren't you using System.IniFiles.TIniFile? It's cross-platform in Seattle. – Ken White Apr 29 '16 at 22:18
  • Because I want the user to edit the ini file. And no, using LoadfromFile also showed the BOM in the memo - so perhaps LoadFromFile isn't as "cross platform" as one would hope? In addition, after using the overloaded version where I specified UTF-8, the BOM no longer shows when using LoadFromFile. – Freddie Bell Apr 30 '16 at 04:50
  • Seems like what you might want instead is more like `TValueListEditor` on Windows, which would probably allow you to still use `TIniFile`. A free-style memo for users to edit name/value pairs isn't usually a good idea. As far as LoadFromFile, I haven't yet had the issue of it not properly detecting the BOM, but then I've never had it added by Notepad when I didn't intend it to be. – Ken White Apr 30 '16 at 04:58
  • There's no TValueListeditor as such in FMX... but.. I probably agree that it wasn't a good idea from a _design_ point of view to use this memo. But I can always make it read-only. :-) – Freddie Bell Apr 30 '16 at 12:32