View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0002690SAS.ПланетаРефакторингpublic21-04-2015 09:2807-11-2015 19:17
Reportervdemidov 
Assigned Tovdemidov 
PrioritynormalSeverityminorReproducibilityhave not tried
StatusresolvedResolutionfixed 
PlatformOSOS Version
Product Version141212 
Target Version151111Fixed in Version151111 
Summary0002690: Добавить определение кодировки ini-файлов при загрузке в ConfigDataProvider
DescriptionСейчас программа при попытке загрузить ini-файл в юникодной кодировке, не загружает ничего. Нужно при загрузке использовать DetectUTFEncoding и конвертировать полученное в текущий тип String.
TagsNo tags attached.
Attached Files

- Relationships
related to 0002877resolvedvdemidov Поддержка utf-8 и utf-16 при загрузке параметров карты в неюникодной версии программы 
child of 0002166resolvedzed Переход на версию Delphi с полной поддержкой юникода 
child of 0002875resolvedvdemidov Символы не из основной локали заменяются на знаки вопроса в истории поиска 
child of 0002878resolvedvdemidov В юникодной версии невозможно сохранить путь к кэшу в юникоде 

-  Notes
(0015647)
vdemidov (manager)
22-04-2015 07:25

Я тут подумал, похоже оптимальным вариантом будет сделать по аналогии с парсером TKmlInfoSimpleParser. То есть при загрузке инишки проверяем ее кодировку и если надо конвертируем ее в UTF8. При загрузке/сохранении параметров-строк выполняем кодирование/декодирование в UTF8. Почти все содержимое ini это ANSI и только несколько строковых параметров может содержать какие-то другие символы (история поиска, пути, шаблоны имен для меток и категорий).
(0015648)
zed (manager)
22-04-2015 07:36

Сохранение в ini это отдельный вопрос. Если их перевести на utf8, то старые версии их резко перестанут понимать. И это, ещё до перехода на юникодную делфи.
(0015650)
vdemidov (manager)
22-04-2015 08:04

Можно сменить формат основного конфига на JSON c обязательной Utf-8 в качестве кодировки :)

Еще можно попробовать, для начала, добавить детектирование наличия utf-8 строк в файле и если есть, то взводить флаг, который будет предписывать читать и сохранять строки в utf-8. В результате версии начиная с некоторой начнут понимать такие конфиги, но не будут принуждать к переходу так сказать. А после перехода на юникод, сделаем принудительное сохранение в utf-8. Но последние актуальные версии будут продолжать нормально работать с такими конфигами.
(0015652)
zed (manager)
22-04-2015 08:08

Вариант со сменой формата на json мне нравится. А ini можно оставить для обратной совместимости, только для чтения (если не найден json). Соответственно, и читать ini всегда как анси.
(0015656)
vdemidov (manager)
22-04-2015 10:06

Значит нужно делать реализацию IConfigDataWriteProvider с записью в JSON.
(0015658)
vasketsov (manager)
22-04-2015 10:42

>Вариант со сменой формата на json
Ну, фактически это означает, что у EXE-хи будут разные конфиги (минимум ДВА), даже если две EXE-хи собирать в одну папку. То есть как бы _при_идентичных_настройках_ проверить наличие или отсутствие бага на другой версии компилятора уже не получится.
Ну и ещё не нравится то, что редактирование его руками может быть весьма нетривиально.

>взводить флаг, который будет предписывать читать и сохранять строки в utf-8
Вот такое поведение представляется куда более разумным. Тем более что при необходимости можно будет сделать флаг, что содержимое было unicode (в т.ч. LE) и сохранять его обратно также.
Пример определения, чего за unicode подсунули (через IsTextUnicode), у меня есть в u_IocpServer.pas. Только что кстати его подправил на тему строк.
(0015665)
vdemidov (manager)
22-04-2015 10:57

>Ну, фактически это означает, что у EXE-хи будут разные конфиги (минимум ДВА), даже если две EXE-хи собирать в одну папку.
Не, речь о переходе текущей обычной версии на новый формат конфига. То есть когда появится юникодная версия, актуальная обычная версия уже должна пользоваться новым форматом конфига.
(0015668)
vasketsov (manager)
22-04-2015 11:05

Так понял. Ну тогда это надо делать заведомо до следующего релиза.
Только надо договориться, что в общие конфиги не будем совать сильно нетривиальные типы данных.
Но я бы всё же предложил ещё сильно подумать насчёт json.
У него отсутствует дуракоустойчивость.
Лишняя скобка - и ппц.
А поскольку конфиги правятся руками,...
А также конфиг сильно распухнет (либо будет нечитаемым), что приведёт к задержке чтения его с диска.
А поскольку та же фигня со всеми zmp, то время старта увеличится.
А zmp делать нечитаемыми нельзя, они в репо падают с изменениями, так что там точно будет куча пробелов всяких.
В общем, потенциально или тормознутое или неудобное решение.
(0015684)
vdemidov (manager)
23-04-2015 07:36

> У него отсутствует дуракоустойчивость.
Убедил. Сейчас мне кажется оптимальным добавить поддержку utf-8 в ini-шки. Остается только придумать метод переключения режима. Возможные варианты:
1. Самый простой вариант завести в ini специальный ключ и проверять его сразу при загрузке, например в секции [SYSTEM]use_utf8=1
2. Пытаться читать все строки файла и определять есть ли там utf-8 или, наоборот, точно не utf-8 строки и в зависимости от этого решать как действовать дальше.
3. Просто забить на совместимость конфигов и перейти на utf-8 принудительно.
(0015685)
vasketsov (manager)
23-04-2015 08:17

>читать все строки файла и определять есть ли там utf-8
Я бы предложил так:
а) при загрузке проверять на unicode и в этом случае в XE2 грузить как есть и сохранять как есть, а в 2007 молча приводить к utf-8 и сохранять потом в utf-8 (вряд ли имеет смысл сохранять в unicode в 2007);
б) если не unicode то надо проверять, что буфер содержит валидную строку utf-8 или сразу по всему буферу (Pointer и Size есть), или лениво и построчно при чтении значения, лично мне кажется проще и быстрее первый вариант сразу, и без [SYSTEM]use_utf8=1 (которую никто и никогда не будет искать и менять в файле при его сохранении в блокноте руками); соответственно если конфиг валиден в смысле utf-8, то и сохранять его в таком же формате (важно для уменьшения размера в том числе, ибо желательно конечно универсальное решение и для конфигов и для zmp;);
в) если не unicode и буфер не валидная utf-8 строка - значит Ansi, тут по желанию можно конвертнуться в utf-8 и сохраняться в нём, а можно оставить Ansi, если не будет сильно трудно.
Это в теории.
(0015693)
vdemidov (manager)
23-04-2015 09:30

> в XE2 грузить как есть и сохранять как есть
Как показала практика в XE2 как есть сохраняет и читает именно в Ansi и будут потери если строка не совпадают с текущей локалью.

> а) при загрузке проверять на unicode и молча приводить к utf-8 и сохранять потом в utf-8
Это можно, но только на случай создания файла нотпадом. Сам САС ни в какой из версий сохранять utf-16 не будет.
> если не unicode то надо проверять, что буфер содержит валидную строку utf-8
Вот в этом и вопрос. Как это правильно делать.

Вариант с отдельным ключом хорош тем, что он позволит не перейти ненароком на utf-8 когда пользователь этого не хочет. Пример:
1. Есть старая версия, которая не понимает utf-8 но в конфиге нет не ansi строк.
2. Запускается версия с поддержкой utf-8, решает что это валидная utf-8 строка и новые строки сохраняет в utf-8, и вводится какое-то значение которое уже не ansi
3. Запускается старая версия и говорит WTF
(0015708)
vasketsov (manager)
23-04-2015 15:39

>позволит не перейти ненароком на utf-8
А, ну то есть параметр будет означать запрет изменения формата? Тогда в нём есть смысл.

>сохраняет и читает именно в Ansi
Это каким способом?
TStringList.ReadFromStream/ReadFromFile?
Потому что у меня есть сомнения насчёт этого в случае ReadFile сотоварищи, которые читают буфер с диска как есть и кладут его в строку не зная её тип, и наоборот пишут всю строку как есть на диск.

>Как это правильно делать
Первая же ссылка на хабре выдаёт пример, правда для веба, что-то типа php, не силён в этом, видел только что не perl. Я про то, где ещё стёб про корейцев.
(0015710)
vdemidov (manager)
23-04-2015 17:41

>>сохраняет и читает именно в Ansi
>Это каким способом?
TMeminifile.Create
Там в XE2 уже есть проверка кодировки открываемого файла по существующему BOM.
А по умолчанию используется Ansi

>Первая же ссылка на хабре выдаёт пример, правда для веба, что-то типа php, не силён в этом, видел только что не perl. Я про то, где ещё стёб про корейцев.
В том то и дело что стеб. А как правильно проверить файл я не знаю. Хотя для двух десятков килобайт и такой способ прокатит.
(0015711)
vasketsov (manager)
23-04-2015 18:48

>стеб
Да я ж про комменты:

// Returns true if $string is valid UTF-8 and false otherwise.
 function is_utf8($string) {
 // From w3.org/International/questions/qa-forms-utf-8.html
 return preg_match('%^(?:
 [\x09\x0A\x0D\x20-\x7E] # ASCII
 | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
 | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
 | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
 | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
 | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
 )*$%xs', $string);
 } // function is_utf8


А вот ещё:
http://phpclub.ru/talk/threads/utf8-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B0-%D0%BD%D0%B0-%D0%B2%D0%B0%D0%BB%D0%B8%D0%B4%D0%BD%D0%BE%D1%81%D1%82%D1%8C.35808/

но всё php - я в нём не бельмеса.

Может быть проще будет по определению из вики сделать:

Символы UTF-8 получаются из Unicode следующим образом:
Unicode UTF-8:
0x00000000 — 0x0000007F: 0xxxxxxx
0x00000080 — 0x000007FF: 110xxxxx 10xxxxxx
0x00000800 — 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 — 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


Теоретически возможны, но не включены в стандарт также:
0x00200000 — 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x04000000 — 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


Короче, судя по всему, это вопрос или прямого однопроходного алгоритма, или регулярного выражения.
(0015712)
vasketsov (manager)
23-04-2015 18:58

Но вообще я бы плясал от IsTextUnicode
https://msdn.microsoft.com/en-us/library/windows/desktop/dd318672(v=vs.85).aspx

и сотоварищи
MultiByteToWideChar
WideCharToMultiByte
возможно флаг WC_ERR_INVALID_CHARS

и результат:

The function returns 0 if it does not succeed. To get extended error information, the application can call GetLastError, which can return one of the following error codes:
•ERROR_INSUFFICIENT_BUFFER. A supplied buffer size was not large enough, or it was incorrectly set to NULL.
•ERROR_INVALID_FLAGS. The values supplied for flags were not valid.
•ERROR_INVALID_PARAMETER. Any of the parameter values was invalid.
•ERROR_NO_UNICODE_TRANSLATION. Invalid Unicode was found in a string.

последнее может быть оно и есть?
(0015714)
vdemidov (manager)
23-04-2015 21:04

Ну регексп это перебор. А вот IsTextUnicode уже интереснее.
Хотя мне все больше хочется повторить то что уже есть из коробки в версии XE2: проверяем BOM в том числе и для utf-8, отсутствие BOM считаем признаком ANSI, по результатам конвертим в текущий тип string.
(0015716)
vasketsov (manager)
24-04-2015 00:07

>отсутствие BOM считаем признаком ANSI
Ничего подобного.
Если нет BOM но залетели внутрь IsTextUnicode - значит прилетел WideString.
См. что я залил себе в парсер kml, это кусок вставки меток из буфера обмена.
Специально оставил как есть чтобы ещё немного поиграться.
Пока строка из буфера обмена забиралась как WideString - Get для неё там отлично работал. Вернул забор в виде Ansi просто потому что мы её копируем в буфер обмена как UTF-8.
(0015717)
vasketsov (manager)
24-04-2015 04:26

Подумалось вот ещё. Может есть софт типа тоталкомандера или нотепада какого (в смысле, на дельфе и открытый), где решена проблема распознавания буфера и кодировок, проверки utf-8? Откуда это официально можно было бы спереть. Есть мысли на эту тему?
(0015719)
zed (manager)
24-04-2015 04:40

Можно сделать настройку: "Файлы без BOM распозновать как:" и список кодировок. По-умолчанию выставить системную или utf-8.
(0015720)
zed (manager)
24-04-2015 04:50

> Есть мысли на эту тему?
Посмотри на Notepad++ (хоть там и с++) - умеет распозновать utf-8 без BOM.
(0015722)
vasketsov (manager)
24-04-2015 06:30

http://doublecmd.sourceforge.net/
Double Commander
использует судя по всему
Summary
Charset Detector - as the name says - is a stand alone executable module for automatic charset detection of a given text.
It can be useful for internationalisation support in multilingual applications such as web-script editors or Unicode editors.
Given input buffer will be analysed to guess used encoding. The result can be used as control parameter for charset conversation procedure.
Charset Detector can be compiled (and hopefully used) for MS Windows (as dll - dynamic link library) or Linux.
Based on Mozilla's i18n component - http://www.mozilla.org/projects/intl/.

-----------State
Version 0.2.6 stable.
The latest version can be found at http://chsdet.sourceforge.net.
(0015723)
vdemidov (manager)
24-04-2015 07:58

А мне кажется, что с этим можно вообще не заморачиваться. Версия скомпиленная в XE2 по-умолчанию все сохраняет в ANSI, то есть ровно так же как есть сейчас. Можно добавить в текущую версию проверку BOM и перекодировку, а со временем в юникодной версии установить принудительное сохранение в utf-8. И все будет работать в обычной версии ничуть не хуже чем сейчас, а в юникодной - лучше.
(0015759)
vdemidov (manager)
26-04-2015 11:34

Блин. Как лень делать работу, которая станет не нужно сразу после перехода на XE2.
(0015760)
vasketsov (manager)
26-04-2015 11:50

Ну тогда надо заранее приготовиться к потоку ссаных тряпок, доделать то что совсем уж не причёсано, и выпустить релиз под XE2. Тогда делать ненужную работу по переходу не придётся. Вся работа будет только нужной.
(0015770)
vdemidov (manager)
26-04-2015 13:34

Ну тогда давай конкретные примеры, когда юникодная версия работает хуже чем текущая.
(0015773)
zed (manager)
26-04-2015 13:39

Я думаю, если внезапно начать собирать ночнушку в XE2, багтрекер треснет от наплыва багов :)
(0016509)
zed (manager)
02-10-2015 19:51

Мне вот сейчас подумалось, что первым делом нам нужно перевести все zmp на юникод. Особенно, в свете того, что появился интерес со стороны французских товарищей и они сейчас могут захотеть писать в params.txt локализованные названия карт. И по-моему, проще всего это добавить флаг 'use_utf8' или положить файлик типа encoding.txt в zmp с актуальной кодировкой всех ini/txt.

Причём, это имеет смысл делать уже сейчас, вне зависимости от того, каким мы компилятором пользуемся.
(0016511)
vdemidov (manager)
02-10-2015 20:43

Просто очень лень вручную делать то, что получим автоматом при переходе на новую версию компилятора. Там детектирование на основе BOM уже есть из коробки.
(0016512)
zed (manager)
02-10-2015 20:47

Не факт, что мы на эту новую версию ещё перейдём. Да и детектирование по bom не такой уж и надёжный способ.
(0016513)
vdemidov (manager)
02-10-2015 20:54

>Не факт, что мы на эту новую версию ещё перейдём.
Это плохо.
>Да и детектирование по bom не такой уж и надёжный способ.
ИМХО он оптимален по соотношению затрачиваемых усилий на реализацию, затрачиваемых при работе ресурсов и полученному результату.
(0016514)
zed (manager)
02-10-2015 21:06

Я бы хотел, чтобы наш следующий релиз уже поддерживал юникод, хотя бы в params.txt.
(0016515)
vdemidov (manager)
02-10-2015 21:09

Я пасс. Я любую поддержку юникода буду добавлять только после перехода на юникодную делфи.
(0016732)
vdemidov (manager)
05-11-2015 07:51

Кажется придумал как добавить более менее вменяемую поддержку юникода в ини файлах в D2007. Делаем в Compatibility наследника TMemIniFile с таким же именем. И добавляем туда недостающее свойство Encoding, поддержку чтения файлов с юникодом и сохранение файла с использованием Encoding. В итоге все ограничится добавлением одного юнита в uses в нужных местах. Недостаток - при использовании одновременно юникодной и неюникодной версий - неюникодная версия будет портить символы не из основной локали. Но если их не будет, то все будет работать прозрачно.
(0016736)
vdemidov (manager)
05-11-2015 22:23

Вроде бы даже работает. Юникодные данные, конечно, теряются после открытия в неюникодной версии, но только те, которые не из текущей локали. То есть не хуже чем было, а по некоторым параметрам лучше.
(0016738)
vdemidov (manager)
06-11-2015 07:42

Осталось придумать по какому признаку сделать принудительное сохранение ini в utf в юникодной версии. Самый простой вариант, после выпуска релиза с поддержкой юникодных конфигов, юникодная версия будет форсировано сохранять в utf-8 или utf-16, а обычная просто будет сохранять существующую кодировку.

- Users who viewed this issue
User List Anonymous (3463x), zed (16x), vdemidov (35x), gma (1x)
Total Views 3515
Last View 09-04-2020 16:54

- Issue History
Date Modified Username Field Change
21-04-2015 09:28 vdemidov New Issue
21-04-2015 09:29 vdemidov Relationship added child of 0002166
21-04-2015 09:29 vdemidov Status new => confirmed
22-04-2015 07:25 vdemidov Note Added: 0015647
22-04-2015 07:36 zed Note Added: 0015648
22-04-2015 08:04 vdemidov Note Added: 0015650
22-04-2015 08:08 zed Note Added: 0015652
22-04-2015 10:06 vdemidov Note Added: 0015656
22-04-2015 10:42 vasketsov Note Added: 0015658
22-04-2015 10:57 vdemidov Note Added: 0015665
22-04-2015 11:05 vasketsov Note Added: 0015668
23-04-2015 07:36 vdemidov Note Added: 0015684
23-04-2015 08:17 vasketsov Note Added: 0015685
23-04-2015 09:30 vdemidov Note Added: 0015693
23-04-2015 15:39 vasketsov Note Added: 0015708
23-04-2015 17:41 vdemidov Note Added: 0015710
23-04-2015 18:48 vasketsov Note Added: 0015711
23-04-2015 18:58 vasketsov Note Added: 0015712
23-04-2015 21:04 vdemidov Note Added: 0015714
24-04-2015 00:07 vasketsov Note Added: 0015716
24-04-2015 04:26 vasketsov Note Added: 0015717
24-04-2015 04:40 zed Note Added: 0015719
24-04-2015 04:50 zed Note Added: 0015720
24-04-2015 06:30 vasketsov Note Added: 0015722
24-04-2015 07:58 vdemidov Note Added: 0015723
26-04-2015 11:34 vdemidov Note Added: 0015759
26-04-2015 11:50 vasketsov Note Added: 0015760
26-04-2015 13:34 vdemidov Note Added: 0015770
26-04-2015 13:39 zed Note Added: 0015773
02-10-2015 19:51 zed Note Added: 0016509
02-10-2015 20:43 vdemidov Note Added: 0016511
02-10-2015 20:47 zed Note Added: 0016512
02-10-2015 20:54 vdemidov Note Added: 0016513
02-10-2015 21:06 zed Note Added: 0016514
02-10-2015 21:09 vdemidov Note Added: 0016515
04-10-2015 15:28 vdemidov Target Version 151010 => 151111
09-10-2015 09:06 vdemidov Relationship replaced parent of 0002166
13-10-2015 09:20 vdemidov Target Version 151111 => 25xxxx
28-10-2015 20:53 vdemidov Relationship added child of 0002875
29-10-2015 11:05 vdemidov Relationship added related to 0002877
30-10-2015 08:57 vdemidov Relationship added child of 0002878
05-11-2015 07:51 vdemidov Note Added: 0016732
05-11-2015 08:07 vdemidov Target Version 25xxxx => 151111
05-11-2015 08:08 vdemidov Relationship replaced child of 0002166
05-11-2015 22:23 vdemidov Note Added: 0016736
06-11-2015 07:42 vdemidov Note Added: 0016738
07-11-2015 19:17 vdemidov Status confirmed => resolved
07-11-2015 19:17 vdemidov Fixed in Version => 151111
07-11-2015 19:17 vdemidov Resolution open => fixed
07-11-2015 19:17 vdemidov Assigned To => vdemidov



Copyright © 2007 - 2020 SAS.Planet Team