Recent

Author Topic: TIniFile couldn't read UTF-8 Unicode text file  (Read 5570 times)

motaz

  • Sr. Member
  • ****
  • Posts: 495
    • http://code.sd
TIniFile couldn't read UTF-8 Unicode text file
« on: April 14, 2014, 09:42:58 am »
I had this problem when I modify the INI file in Windows 7 (32bit), that TIniFile coudln't read information inside it, when checking file type in Linux using (file) command it gives:

Tasjeel.ini: UTF-8 Unicode (with BOM) text, with CRLF line terminators

using Memo1.Lines.LoadFromFile works fine, but ini.ReadString returns nothing, the origional file in Linux is:

Tasjeel.ini: UTF-8 Unicode text

this works fine in Linux and Windows

is it a bug that I should report, or it is already known

Attached is the sample and the Unicode with BOM file (Tasjeel.ini)

howardpc

  • Hero Member
  • *****
  • Posts: 4144

motaz

  • Sr. Member
  • ****
  • Posts: 495
    • http://code.sd
Re: TIniFile couldn't read UTF-8 Unicode text file
« Reply #2 on: April 14, 2014, 12:10:43 pm »
Thanks for the link
I have choose the solution of modifying BOM Unicode to Non-BOM Unicode, because the solution of using TFileStream instead of file name have a bug: it duplicates the section when writing into INI File using stream.

This is my modified code that works fine, except that there is a missing truncation of file while converting into non-BOM Unicode file:

Code: [Select]
var
  fileName: string;
  ini: tiniFile;
  FileStream: TFileStream;
  MarkHolder: DWord;
  Contents: string;
begin
  FileName:= 'Tasjeel.ini';
  FileStream := TFileStream.Create(FileName, fmOpenReadWrite);
  MarkHolder := FileStream.ReadDWord;
  if (MarkHolder and $00BFBBEF) = $00BFBBEF then
  begin
      FileStream.Position := 3;
      Memo1.Lines.Add('BOM');
      SetLength(Contents, FileStream.Size - 3);
      FileStream.Read(Pointer(Contents)^, FileStream.Size - 3);
      FileStream.Position:= 0;
      FileStream.Write(Pointer(Contents)^, length(Contents));
  end
  else
  begin
    Memo1.Lines.Add('Not BOM');
  end;
  FileStream.Free;

  Ini := TIniFile.Create(fileName);

  Memo1.lines.Add(ini.ReadString('Settings', 'Database', 'No database'));
  Ini.WriteString('Settings', 'NewParam', 'Azzoz');
  ini.Free; 

circular

  • Hero Member
  • *****
  • Posts: 4471
    • Personal webpage
Re: TIniFile couldn't read UTF-8 Unicode text file
« Reply #3 on: April 14, 2014, 04:10:24 pm »
Hello motaz,

In order to truncate the file, you can close the stream and open it again with fmCreate.

Note that FileStream.ReadDWord will crash if the file is less than 4 bytes.

The check on the MarkHolder is not correct. The mask is $00ffffff to check the values of the first bytes. So it is (MarkHolder and $00FFFFFF) = $00BFBBEF.

Also this is a low endian interpertation of the value. So you need to be sure that it is the way it is retrieved. To do that you can write instead:
Code: [Select]
MarkHolder := NtoLE(FileStream.ReadDWord);
Regards
Conscience is the debugger of the mind

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: TIniFile couldn't read UTF-8 Unicode text file
« Reply #4 on: April 14, 2014, 06:47:42 pm »
The check on the MarkHolder is not correct. The mask is $00ffffff to check the values of the first bytes. So it is (MarkHolder and $00FFFFFF) = $00BFBBEF.
My mistake. I just corrected the mask on my post. Thanks.

motaz

  • Sr. Member
  • ****
  • Posts: 495
    • http://code.sd
Re: TIniFile couldn't read UTF-8 Unicode text file
« Reply #5 on: April 15, 2014, 12:21:22 am »
Thankyou all for your help

 

TinyPortal © 2005-2018