Возникла задача работать с Ini файлами в Unicode
Использую TMemIniFile
В результате, если файл в кодировке UTF8 (кодовая страница 65001), то не считывает ничего.
Если копаться в исходниках, то функция из модуля SysUtils
function TMBCSEncoding.GetCharCount(Bytes: PByte; ByteCount: Integer): Integer;
begin
Result := UnicodeFromLocaleChars(FCodePage, FMBToWCharFlags,
PAnsiChar(Bytes), ByteCount, nil, 0);
end;
Возвращает 0. Ну и дальше понятно, что ничего никуда не загружается.
Использую так:
Непосредственно в сам Ini файл с помощью Notepad++ добавил несколько специфичных символов с умляутами (всякие галочки над буквами), чтобы сразу посмотреть результат.
Но, как уже сказал, вообще ничего не считалось. Пробовал в разных вариантах. Читает только в TEncoding.ASCII, TEncoding.Default, TEncoding.UTF7. В остальных нет.
Если делаю так:
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
18-02-2019 09:48 | Комментарий к предыдущим ответам
Странно, не знал, что проблемы с INI файлом могут быть. Проверено, что обычный INI файл (правда, в Lazarus) без проблем цепляет UTF-8 кодированные значения в INI файлах, проблем вообще никаких. Правда, имена ключей и секций у меня были только англоязычными, возможно, из-за этого всё работало. Но значения по меньшей мере были на английском, русском и французском (другие нафиг не надо было).
Задумка как раз и состояла в том, что тексты должны читать другие люди и даже на тех языках, в которых я вообще ничего понять не смогу :-)
Странно, но облазив весь интернет я не нашел решения этого вопроса.
И чтобы помочь другим приведу вариант решения, который заработал у меня.
Совсем не оптимальный, но другого не нашел, а время поджимает чтобы продолжать искать просто лучшие пути уже решенной задачи.
Загружаю Ini файл в TMemoryStream
Затем копирую содержимое в буфер. Наверно можно было обойтись просто ссылкой на Ms.Memory, но так не пробовал.
Ms := TMemoryStream.Create;
Try
Ms.LoadFromFile(TranslationFile);
SetLength(Buf, Ms.Size);
Ms.Read(Buf[0], Ms.Size);
I := TEncoding.GetBufferEncoding(Buf, Encoding, TEncoding.UTF8);
CodePage := Encoding.CodePage;
finally
FreeAndNil(Ms);
end;
Цель этого действия определить кодировку.
Затем, танцы с бубном :) вокруг загрузки в TStringList
Если просто вызвать LoadFromFile, то теряются спецсимволы. (Может только в моей конфигурации?)
Но именно из-за этого делаю следующим образом
Считываю из файла в строку без преобразования кодировки
Затем присваиваю переменной String, что можно в принципе не делать (это мне так удобнее было для отладки)
RBS:RawByteString;
S:String;
.....
AssignFile(Txt, TranslationFile);
Reset(Txt);
while Not Eof(Txt) do
begin
Readln(Txt, RBS);
S := RBS;
Fs.Add(S);
end;
closeFile(Txt);
Затем уже создаю TMemIniFile в памяти
и копирую ему считанный список строк
После этого TranslatedMemIni содержит реальные данные Unicode и с ними можно работать обычным способом для Ini файлов.
Кстати, следующей проблемой была необходимость отобразить данные Unicode в CxGrid от DevExpress.
Опять же странно, но очень мало информации по данной теме находится в поиске Яндексом и то вся о том, что CxGrid не поддерживает Unicode и т.п.
Это чушь.
Использовал таблицу в памяти TdxMemData
и при создании полей для нее нужно просто выбрать тип не просто String, а WideString и все корректно отображается.
Сначала же, если тип поля объявлен просто String
присвоение значения методом FieldByName('Field').asString преобразовывало спецсимволы с умляутами
После того, как заменил на WideString - работает.
Это все для тех, кто будет искать подобные ответы.
P.S.
Если есть другие варианты решения данной проблемы или улучшения данного метода пишите сюда несмотря на давность этого сообщения.
Чтобы не заморачиваться с перекодировками Unicod'а, каковые перекодировки зачастую
работают довольно задумчиво, можно написать свой собственный перекодировщик. Он будет
символы Unicode, которые не ASCII, перекодировать во что-то вроде %XXXX, где XXXX-четыре
шестнадцатеричные цифры. И, соответственно, обратно тоже. Если такой перекодировщик у вас
будет, то можно писать не только в ini-файл, а вообще во все "текстоподобное".
Сам я с такой проблемой сталкивался, писать надо было и в ini-файл, и в текстовый, много
куда. Если есть свой "личный" перекодировщик - никаких проблем. Если только не надо, чтобы
этот текст читал кто-то другой, вот тогда - не прокатит...
Код перекодировщика могу дать, не жалко... :-)
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.