Кодировка Win1251 опять.....

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

[Решено] Кодировка Win1251 опять.....

Сообщение SergK » 14.02.2017 20:02:07

Спасибо всем за ответы, особое спасибо за ответы приведшие к просветлению SSerge, LearnMagic
Надо сказать, что ,к сожалению, я повел себя как "истинный русский по Задорнову", т.е. читаю инструкцию только если что-то не получается.

И так резюмирую, то что открыл для себя.
Сразу оговорюсь, что все о чем я пишу касается только программ с LCL т.е. Lazarus, CodeTyphon. Программы на "голом" FPC отдельная тема, там я не разбирался.

Итак, разработчики FPC движутся в сторону поддержки UTF8 (юникода) достаточно большими шагами.
Так раньше (до версии FPC 3.0) многие файловые функции такие как AssignFile(), MkDir(), FileExists() ну и многие, многие другие
требовали аргументы- имена файлов в кодировке Win1251 (в случае русской Windows, конечно) или быть точнее в системной кодировке.
А поскольку все переменные (и константы набираемые в редакторе) обычно в кодировке UTF8 то приходилось менять кодировку с помощью UTF8ToSys()
т.е. примерно так :
AssignFile(...,UTF8ToSys(...)), MkDir(UTF8ToSys(...)), FileExists(UTF8ToSys(...)) и так далее
Или для некоторых функций существовали UTF8 двойники Например FileExistsUTF8(), которые уже использовались без перекодировки аргумента (без UTF8ToSys() )
То же касается некоторых методов таких, как например TStrings.SaveToFile(), TStringList.SaveToFile() ну и так далее.....

Теперь (начиная с версии FPC 3.0 т.е Laz 1.6) Эти файловые функции такие как AssignFile(), MkDir(), FileExists() ну и многие, многие другие
требуют аргументы- имена файлов в кодировке UTF8 и теперь можно писать без UTF8ToSys()
AssignFile(...,...), MkDir(...), FileExists(...)
И можно забыть про функции "UTF8 двойники" такие как FileExistsUTF8()
т.е. FileExistsUTF8() и FileExists() будут работать АБСОЛЮТНО ОДИНАКОВО ПРИ ЛЮБЫХ АРГУМЕНТАХ..... ПРОВЕРЯЛ. это так....
То же касается некоторых методов таких, как например TStrings.SaveToFile(), TStringList.SaveToFile() ну и так далее.....

Для того же, чтобы не переписывать и не править весь код где написано:
AssignFile(...,UTF8ToSys(...)), MkDir(UTF8ToSys(...)), FileExists(UTF8ToSys(...)) или FileExistsUTF8() .....
функции UTF8ToSys(), UTF8ToAnsi() и обратные к ним SysToUTF8(), AnsiToUTF8() оставлены как функции пустышки ....
т.е они ничего не делают, а просто возвращают аргумент.
При этом функции типа UTF8ToCP1251(), UTF8ToWinCP(), совсем не пустышки, а выполняют то что обещано исправно !!!!

С этим я и столкнулся в том тестовом примере что привел в исходном посте....

Но внимание !!!! не все функции стали работать с UTF8 например UpperCase() и UTF8UpperCase() работают по разному и сейчас ..... ПРОВЕРЯЛ !!!!
Ну и другие строковые функции тоже.... (функции преобразования строк)
Все мною сказанное верно только для функций где аргументы это имена файлов, каталогов.....

Теперь далее... Для решения разных вопросов совместимости есть у компилятора режим с клюем -dDisableUTF8RTL, при котором вышеупомянутые функции
начинают требовать аргументы в кодировке Win1251, как и раньше, до версии FPC 3.0, но при этом и функции UTF8ToSys(), UTF8ToAnsi() начинают работать как и раньше, перестают быть пустышками.
т.е. в Этом режиме функции FileExistsUTF8() и FileExists() снова будут работать по разному если строка-аргумент содержит русские буквы.
Как откомпилировать проект с этим параметром кому интересно могу подсказать.

Ну например, кто-то написал в своей программе AssignFile(...,UTF8ToCP1251(...)) вместо AssignFile(...,UTF8ToSys(...)), то понятно что данная программа будет корректно работать на под FPC < 3.0 и Русской виндой
при этих условиях UTF8ToCP1251, UTF8ToSys работают одинаково. Но если это откомпилировать FPC 3.0 т.е Laz 1.6 то увы, будет ошибка. Юникодовую строчку преобразуем в CP1251, а функция ждет имя файла в Юникоде.
конечно, по уму надо AssignFile(...,UTF8ToCP1251(...)) заменить на теперь уже, если обратно не возвращаться на AssignFile(...,...), или, если возможен возврат к компилятору FPC < 3.0 на AssignFile(...,UTF8ToSys(...))
А если нет возможности исправить исходники, мозгов не хватает, слишком исходники запутанные, есть вариант откомпилировать проект с ключом -dDisableUTF8RTL и он снова заработает.

А сейчас я расскажу из-за чего я вообще сделал исходный пост.
Есть некоторый проект(ик) использующий ZeosDB (ZeosDBO) фиг знает как правильно... и базу firebird.
Писалось исходно используя CodeTyphon какой версии не скажу, так как склероз с пенсией совсем не за горами.
Но при памяти компилировалось в CodeTyphon 5.5 и все сносно работало.
И вот при перекомпиляции "ради прикола" в Lazarus 1.6, Lazarus 1.7 (транковый) и CodeTyphon 5.9 (до установки 6.0 руки не дошли)
Проект отказывался работать если база данных или(и) клиентская библиотека лежала в каталоге с русскими буквами.
Сначала я думал что все дело в версии ZeosDB (ZeosDBO) и даже качал разные ревизии с их транка и подбирал, "чтоб заработало"
Но потом убедился, что все зависит от компилятора или среды уж как лучше сказать....
Сначала думал ну вот 3.1 до и после, но тут тоже незадача
L 1.6 компилятор 3.0 не работает
ct 5.5 компилятор 3.1.1 работает
L 1.7 компилятор 3.1.1 не работает
ct 5.9 компилятор 3.1.1 не работает
Тогда я решил, проверить, как работают функции UTF8ToSys(), UTF8ToCP1251(), ну и другие под разными компиляторами, средами.
Результат удивил, показал явную связь работоспособности ZeosDB на каталоге с русскими буквами с работой UTF8ToSys
Вот я его и опубликовал, и спросил почему?
Когда я осознал, все то что написал выше, перекомпилировал свой проект с ключом -dDisableUTF8RTL, и о чудо, он заработал и каталоге с русскими буквами и откомпилированный любым из перечисленных компиляторов...
Как оказалось, в ct 5.5 компилятор настроен так, что он изначально (по умолчанию) компилирует с ключом -dDisableUTF8RTL, но его можно отключить.
С версии 5.6 авторы ct от этой политики отказались. Поэтому так и получается..


Вывод: Увы, разработчики ZeosDB не учитывают новые реалии, грубо говоря, ГРУБО, навставляли где-то что-то вроде AssignFile(...,UTF8ToCP1251(...)), и приходится компилировать с ключом -dDisableUTF8RTL,
и при этом не использовать новые стандарты в плане файловых функций. Или забить на то, что базу и клиентскую библиотеку нельзя будет класть по пути с русскими буквами.
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

Re: Кодировка Win1251 опять.....

Сообщение vitaly_l » 14.02.2017 20:24:04

SergK писал(а):и приходится компилировать с ключом -dDisableUTF8RTL,

:?: Вопрос:
:idea: А можно ли ВРЕМЕННО отключить UTF8, прямо в функции, с помощью директивы, по типу: {-UTF8} и потом снова включить {+UTF8} ???

.
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Кодировка Win1251 опять.....

Сообщение SergK » 14.02.2017 22:32:24

vitaly_l писал(а): :?: Вопрос:
:idea: А можно ли ВРЕМЕННО отключить UTF8, прямо в функции, с помощью директивы, по типу: {-UTF8} и потом снова включить {+UTF8} ???
.


Если вопрос ко мне, то я не знаю..
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

Re: Кодировка Win1251 опять.....

Сообщение pi1 » 25.03.2017 17:02:16

Это еще что, раньше было все просто. Надо тебе 1251, подсуетись, добавь utf8tocp1251 и получи результ. А теперь оно как то само конвертится и х.. знает когда верно конвертится, а когда и не конвертится ваще. Конкретно вот. Есть модуль вывода на печать через Ole-объект (печать на принтер/фискальный регистратор от Штрих-М). Driver := CreateOleObject('Addin.DRvFR');
Driver.Connect();
Driver.StringForPrinting:=utf8tocp1251('Тестовая строка');
Driver.PrintString();
Driver.Disconnect;
Так вот ЗДЕСЬ ТЕПЕРЬ utf8tocp1251 не работает. Как обойти не знаю. Версия 1.6 Компилятор 3.0. На версиях ниже 1.0 работало точно. И тоже волнует вопрос об временном отключении в одном модуле . Там, в свойствах проекта, где можно выбрать -dDisableUTF8RTL, есть фишка - цели и стоит * . Вопрос- как туда указать, что только для одного юнита. Протая подстановка unit1 вместо * не сработала :(

Добавлено спустя 30 минут 20 секунд:
Случайно набрал (по наитию) str:widestring; str:=utf8tosys('Тестовая строка'); Driver.StringForPrinting:=str;
Driver.PrintString(); Распечаталась корректно. Повезло однако, вчера весь день тыкался. Нужно значит - str:widestring, тогда здесь str:=utf8tosys сработало.

Добавлено спустя 53 минуты 1 секунду:
Осталось добавить, что нужно внимательно анализировать логику ситуации (что и не было сделано к сожалению). То есть если на выходе не козазябры, а вопросы, то причина не в кодировке, а в неверном формате данных ввода.
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Re: Кодировка Win1251 опять.....

Сообщение vitaly_l » 25.03.2017 19:19:34

pi1 писал(а):Так вот ЗДЕСЬ ТЕПЕРЬ utf8tocp1251 не работает. Как обойти не знаю.

UTF8ToWinCP
Аватара пользователя
vitaly_l
долгожитель
 
Сообщения: 3333
Зарегистрирован: 31.01.2012 16:41:41

Re: Кодировка Win1251 опять.....

Сообщение alexs » 25.03.2017 19:55:20

Там достаточно просто просто
Код: Выделить всё
var
  WS:widestring;
  S:string;
begin
  S:='Тестовая строка';  //Ну это может как параметр в процедуру быть
  WS:=S; //Вот волшебное присваивание
  Driver.StringForPrinting:=WS;


У меня вот именно так всё и сделано - правда фискальник атоловский.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Кодировка Win1251 опять.....

Сообщение pi1 » 29.03.2017 12:28:10

5 лет эти чудо принтеры от Штрих-М и Атол никому нахрен не нужны были кроме сетевиков и самих этих фирм с их ПО. Обычный китайский принтер чеков был подешевле. Да и настройка у такого - уровень домохозяйки. Последний раз возился с этим чудом программистской мысли в 2012 году. Поэтому не заметил, что формат поменяли на widestring. А сейчас пролоббировали и теперь работы будет всем. Есть правило, что управляющая система должна быть на порядок умней управляемой системы. Это основа стабильного функционирования этих систем. Здесь же ФР = очень сложная машинка. Год назад в магазине свет перемигнул и на компе менеджера слетела винда, а у кассира это самое само перешло в режим налогового инспектора. Винду восстановил за 5 минут, а пароль налогового инспектора узнавал пол дня. ПО от Штрих-М (АРМ кассира) ессно не работало. Конечно если только этим и заниматься, то надо жить в Москве, иначе это не прокормит. А выезд спеца в "колхоз" за 100 км будет ИП в копеечку выходить. Так что работу всем дали.
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Re: Кодировка Win1251 опять.....

Сообщение alexs » 29.03.2017 15:30:47

Тут куча вопросов к самому законодательству. Очень не проработанная тема.
По факту можно както работать только в ретайле. А чуть сложнее обычного розничного магазина - и всё.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4053
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Кодировка Win1251 опять.....

Сообщение pi1 » 03.04.2017 13:28:18

Большое человеческое спасибо vitaly_l за подсказку.
UTF8ToWinCP - рулит, если нужно использовать запуск командной строки из своего проекта (а в строке присутствует кириллица).
Аватара пользователя
pi1
новенький
 
Сообщения: 59
Зарегистрирован: 19.04.2012 18:11:24
Откуда: г.Зеленокумск

Пред.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot], Yandex [Bot] и гости: 32

Рейтинг@Mail.ru