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

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

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

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

Сообщение SergK » 12.02.2017 20:55:06

Программа
Код: Выделить всё
uses LConvEncoding, LazUTF8;

{$R *.lfm}

{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
  var Fout : TextFile;
      myStr : String;
begin
  AssignFile(Fout,'D:\Laz_project\Test-codepage\aaa.txt');
  Rewrite(Fout);
  myStr := 'Primer stroki Пример строки';
  WriteLn(Fout,'---------->    ' + myStr);
  WriteLn(Fout,'UTF8ToSys->    ' + UTF8ToSys(myStr) );
  WriteLn(Fout,'UTF8ToCP1251-> ' + UTF8ToCP1251(myStr) );
  WriteLn(Fout,'UTF8ToConsole->' + UTF8ToConsole(myStr) );
  CloseFile(Fout);
end;


Компилировалась и исполнялась под операционной системой Windows 8.1 с помощью:
1) Lazarus 1.6.2 + Fpc 3.0.0 -Официальный дистрибутив с официального сайта.
2) Lazarus 1.7 + Fpc 3.1.1 - скаченные и откомпилированные с SVN серверов версии (ревизии) от 2.02.2017
3) CodeTyphon ver 5.5 + Fpc 3.1.1 который в комплекте
4) CodeTyphon ver 5.9 + Fpc 3.1.1 который в комплекте

Получился файл в 1, 2, 4 случае если открывать его в кодировке 1251 (редактором "блокнот")

----------> Primer stroki Пример строки
UTF8ToSys-> Primer stroki Пример строки
UTF8ToCP1251-> Primer stroki Пример строки
UTF8ToConsole->Primer stroki Пример строки

Т.е. UTF8ToSys, и UTF8ToConsole не сработало, зато сработало UTF8ToCP1251

в 3 случае получилось

----------> Primer stroki Пример строки
UTF8ToSys-> Primer stroki Пример строки
UTF8ToCP1251-> Primer stroki Пример строки
UTF8ToConsole->Primer stroki ЏаЁ¬Ґа бва®ЄЁ


Т.е. UTF8ToSys, и UTF8ToConsole в этом случае сработало, зато не сработало UTF8ToCP1251
(прим ЏаЁ¬Ґа бва®ЄЁ это Пример строки в кодировке 866 - проверено)

Почему так ??? почему не работают UTF8ToSys, UTF8ToConsole, UTF8ToCP1251 все вместе...
Что у кого получается при таких экспериментах ???

Кстати, есть небольшой проектик где используется ZeosDB база данных firebird и если явно не указать в настоечном файле где хранится база данных, то она ищется в каталоге с exe-шкой так вот, если этот проект откомпилировать CodeTyphon ver 5.5 + Fpc 3.1.1 который в комплекте то программа работает в каком бы каталоге не находилась программа с базой данных. А вот с другими перечисленными компиляторами, только если в по пути в котором нет русских букв.
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

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

Сообщение zub » 12.02.2017 21:22:17

Выключи LConvEncoding - результат будет другим. LConvEncoding инклудит lazutils_defines.inc посмотри настройки там
zub
долгожитель
 
Сообщения: 2024
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение SergK » 12.02.2017 21:45:22

Выключи LConvEncoding - результат будет другим. LConvEncoding инклудит lazutils_defines.inc посмотри настройки там

Если выключить то UTF8ToCP1251 работать не будет совсем. Она описана только там
Что смотреть в lazutils_defines.inc ?

Добавлено спустя 10 минут 18 секунд:
Убрал LConvEncoding, перекомпилировал Lazarus 1.6.2 + Fpc 3.0.0 -Официальный дистрибутив с официального сайта.
Убрал WriteLn(Fout,'UTF8ToCP1251-> ' + UTF8ToCP1251(myStr) ); поскольку UTF8ToCP1251 описана в LConvEncoding результат:
----------> Primer stroki Пример строки
UTF8ToSys-> Primer stroki Пример строки
UTF8ToConsole->Primer stroki Пример строки
Т.е. UTF8ToSys, UTF8ToConsole все равно не работают....
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

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

Сообщение Снег Север » 12.02.2017 22:21:31

Интересно, какая религия заставляет писать через WriteLn? Что мешает писать в TStingList и безо всяких проблем сохранять текст в utf8?
Аватара пользователя
Снег Север
энтузиаст
 
Сообщения: 897
Зарегистрирован: 27.11.2007 16:14:47

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

Сообщение MysticCoder » 12.02.2017 23:22:07

UTF8ToSys вроде же кодирует в системную кодировку, т.е. UTF-16 в случае винды, отсюда кракозябры по 2 байта на символ, а в консоли видимо стоит по умолчанию кодировка cp1251 однобайтовая, если её поменять через SetConsoleCP или SetConsoleOutputCP(1200), то UTF8ToSys будет отображать нормально, наверное.
MysticCoder
новенький
 
Сообщения: 88
Зарегистрирован: 14.09.2013 00:20:28

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

Сообщение zub » 12.02.2017 23:38:21

>>Т.е. UTF8ToSys, UTF8ToConsole все равно не работают....
я не обратил внимание что вы используете пример в лазаре, не в голом фпц.
Дело в том что LCL уже использует LConvEncoding и включай его или не включай - без разницы.
в голом фпц результат вотэтого
Код: Выделить всё
uses {LConvEncoding,}LazUTF8;
var Fout : TextFile;
    myStr : String;
begin
  AssignFile(Fout,'D:\aaa.txt');
  Rewrite(Fout);
  myStr := 'Primer stroki Пример строки';
  WriteLn(Fout,'---------->    ' + myStr);
  WriteLn(Fout,'UTF8ToSys->    ' + UTF8ToSys(myStr) );
  //WriteLn(Fout,'UTF8ToCP1251-> ' + UTF8ToCP1251(myStr) );
  WriteLn(Fout,'UTF8ToConsole->' + UTF8ToConsole(myStr) );
  CloseFile(Fout);
end.   

будет:
----------> Primer stroki Пример строки
UTF8ToSys-> Primer stroki Пример строки
UTF8ToConsole->Primer stroki Пример строки

Чудеса))

Смотреть надо вотсюда
Код: Выделить всё
// Add defines here. This file should be included in all LazUtils units headers


{$undef UTF8_RTL}  // FPC >= 2.7.1 with codepages and default string = CP_UTF8
{$undef ACP_RTL}   // FPC >= 2.7.1 with codepages and default string = CP_ACP
{$undef NO_CP_RTL} // FPC < 2.7.1 before string codepages


{$ifdef FPC_HAS_CPSTRING}
  {$ifndef DisableUTF8RTL}
    {$define UTF8_RTL}
  {$else DisableUTF8RTL}
    {$define ACP_RTL}
  {$endif DisableUTF8RTL}
{$else FPC_HAS_CPSTRING}
  {$define NO_CP_RTL}
  {$undef DisableUTF8RTL}
{$endif FPC_HAS_CPSTRING}   
zub
долгожитель
 
Сообщения: 2024
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение SergK » 13.02.2017 00:11:10

Так значит, эксперименты продолжаются .....
Подопытный кролик : Lazarus 1.6.2 + Fpc 3.0.0 -Официальный дистрибутив с официального сайта.
Прислушавшись к словам zub и по его наводке удалил файл lazutils_defines.inc
Вернув при этом на родину Uses LConvEncoding и WriteLn(Fout,'UTF8ToCP1251-> ' + UTF8ToCP1251(myStr)
Точнее я его, файл lazutils_defines.inc надо сказать не удалил совсем а лишь сделал пустым, чтобы не трогать те файлы в которых он вызывается.
К этому подвигли не только слова, zub а еще и тот факт, что в составе CodeTyphon ver 5.5 на соответствующем месте файла lazutils_defines.inc нет вообще.
Но там и тех файлах где инклюдится lazutils_defines.inc в других компиляторах, упоминания о нем нет.
Получил результат:

----------> Primer stroki Пример строки
UTF8ToSys-> Primer stroki Пример строки
UTF8ToCP1251-> Primer stroki Пример строки
UTF8ToConsole->Primer stroki Пример строки
UTF8ToAnsi-> Primer stroki Пример строки


т.е. UTF8ToSys, заработала как и хотелось.... , UTF8ToCP1251 как работала так и работает, правильно....
и UTF8ToConsole заработала, но не так как надо бы, или как предполагалось она выдала текст в кодировке 1251, а ожидалось в кодировке 866

Но остались вопросы:
1) Почему в CodeTyphon ver 5.5 где исходно Верно работали UTF8ToSys, и UTF8ToConsole не работает UTF8ToCP1251 ?
2) Почему в Lazarus 1.6.2 + Fpc 3.0.0 после обнуления файла lazutils_defines.inc UTF8ToConsole заработала, но неверно, не так как в CodeTyphon ver 5.5 ?
3) Хотелось бы понять, какой конкретно параметр препроцессора из lazutils_defines.inc повлиял на работоспособность UTF8ToSys, и UTF8ToConsole ?
Есть идеи...?
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

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

Сообщение zub » 13.02.2017 00:18:16

>>, какой конкретно параметр препроцессора из lazutils_defines.inc повлиял на
{$define UTF8_RTL}
Особо сильно с ним баловаться ненадо, лцл может сломаться.
Пока лцл не станет полноценно поддерживать "новые" строки - будем терпеть такие костыли
zub
долгожитель
 
Сообщения: 2024
Зарегистрирован: 14.11.2005 23:51:26

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

Сообщение SergK » 13.02.2017 00:48:05

MysticCoder
UTF8ToSys вроде же кодирует в системную кодировку, т.е. UTF-16 в случае винды, отсюда кракозябры по 2 байта на символ, а в консоли видимо стоит по умолчанию кодировка cp1251 однобайтовая, если её поменять через SetConsoleCP или SetConsoleOutputCP(1200), то UTF8ToSys будет отображать нормально, наверное.


Уважаемый MysticCoder Ваши рассуждения о том что UTF8ToSys преобразует строку в UTF-16 и потому там тоже "кракозябры", увы не верны. потому что, если вы внимательно посмотрите на приводимые мной результаты вывода то увидите что в случаях 1,2,4 (смотри исходный пост) после ---------->, и после UTF8ToSys-> , и после UTF8ToConsole-> идет абсолютно одинаковый текст "Primer stroki Пример строки", а это значит что функции UTF8ToSys, UTF8ToConsole текст вообще никак не преобразовали, Более того существуют редакторы которые могут читать текст не только в кодировке 1251 а и других, например встроенный редактор far'a. и открыв в нем текст, можно меняя кодировку в которой надо интерпретировать текст понять, в какой на самом деле кодировке тот или иной текст. Так что я Вам ответственно заявляю, что в исходном посте в случаях 1, 2, 4 текст
1) Исходный после ----> в UTF8
2) после UTF8ToSys-> в UTF8
3) после UTF8ToCP1251-> в кодировке 1251
4) после UTF8ToConsole-> в UTF8

в случае 3 ( CodeTyphon ver 5.5 )
1) Исходный после ----> в UTF8
2) после UTF8ToSys-> в кодировке 1251
3) после UTF8ToCP1251-> в UTF8
4) после UTF8ToConsole-> в кодировке 866

а в Lazarus 1.6.2 после моих модификаций
1) Исходный после ----> в UTF8
2) после UTF8ToSys-> в кодировке 1251
3) после UTF8ToCP1251-> в кодировке 1251
4) после UTF8ToConsole-> в кодировке 1251
SergK
новенький
 
Сообщения: 19
Зарегистрирован: 05.03.2011 18:24:51

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

Сообщение MysticCoder » 13.02.2017 06:49:55

SergK писал(а): Ваши рассуждения о том что UTF8ToSys преобразует строку в UTF-16 и потому там тоже "кракозябры", увы не верны. потому что, если вы внимательно посмотрите на приводимые мной результаты вывода то увидите


Да, действительно, упустил из виду, что в первой строке результата та же самая строка выходит. Однако, то что у вас такие результаты вовсе не значит, что мои рассуждения не верны(да, скорее всего они неверны:D)

Вообще, в прошлый раз когда этим вопросом занимался я нарыл, что Utf8ToAnsi кодирует из Utf8 в ANSI кодировку, где ANSI значит системная, и может быть какой угодно в зависимости от ОС и настроек. В винде за системную считается вроде как UTF-16. Сейчас же открываю справку лазаруса по Utf8ToAnsi, а там
Utf8ToAnsi converts an utf8-encode unicode string to an ansistring. It converts the string to a widestring and then converts the widestring to an ansistring.

For this function to work, a widestring manager must be installed.


Т.е. я понимаю, что оно просто кодирует в ansistring, т.е. в принципе то ничего с кодировкой и не делает. Что довольно странно. В справке делфи аналогичная функция по описанию делает то что я говорил:
Converts a UTF8 string to a string of Ansi characters.

Call Utf8ToAnsi to convert a UTF-8 string to Ansi. S is a string encoded in UTF-8. Utf8ToAnsi returns the corresponding string that uses the Ansi character set.


Я в этом не очень понимаю и может мои представления неверны, может поправите?
MysticCoder
новенький
 
Сообщения: 88
Зарегистрирован: 14.09.2013 00:20:28

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

Сообщение SSerge » 13.02.2017 06:58:21

SergK писал(а):почему не работают UTF8ToSys


Потому что RTL при использовании с лазарусом установлена в системную кодировку UTF8;
Следовательно, строка в UTF8 перекодироваться этой функцией не будет.

...Вы вот это прочитали?
http://wiki.freepascal.org/LCL_Unicode_Support/ru
http://wiki.freepascal.org/Better_Unico ... Lazarus/ru
SSerge
энтузиаст
 
Сообщения: 780
Зарегистрирован: 12.01.2012 05:34:14
Откуда: Барнаул

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

Сообщение LearnMagic » 13.02.2017 11:14:44

Не забудьте посмотреть первоисточник http://wiki.lazarus.freepascal.org/Lazarus_1.6.0_release_notes
LazUtils
SysToUTF8 does not convert
Similar: AnsiToUTF8
Old behaviour: SysToUTF8 converted on Windows from system codepage to UTF-8.
New behaviour: Does not change the string (unless you disable the new UTF-8 mode).
Reason: function was mainly used for converting strings from the RTL, which is now talking UTF-8.
Remedy: use function WinCPToUTF8 from unit LazUTF8 or CP1251ToUTF8 from unit LConvEncoding.
UTF8ToSys does not convert
Similar: UTF8ToAnsi
Old behaviour: UTF8ToSys converted on Windows UTF-8 to system codepage.
New behaviour: Does not change the string (unless you disable the new UTF-8 mode).
Reason: function was mainly used for converting strings for the RTL, which is now talking UTF-8.
Remedy: use function UTF8ToWinCP from unit LazUTF8 or UTF8ToCP1251 from unit LConvEncoding.

Сам в это "упёрся" после перехода с lazarus 1.4 на 1.6
Так же нужно внимательно смотреть на функции работы с файлами. Например использовать DeleteFileUTF8, а не просто DeleteFile.
И ни кто не запрещает глянтуь в исходниках на реализацию той или иной функции :)
LearnMagic
новенький
 
Сообщения: 12
Зарегистрирован: 10.11.2016 23:13:38

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

Сообщение mrkaban » 13.02.2017 12:17:47

Я прошу прощения, может не понял, не разобрался, и не в тему, но в своём проекте при работе с текстовыми файлами кодироку менял в другой строке

AssignFile(Name, UTF8ToSys('Name.txt'));
mrkaban
новенький
 
Сообщения: 46
Зарегистрирован: 28.05.2016 09:48:18

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

Сообщение beria » 13.02.2017 16:48:22

MysticCoder писал(а):В винде за системную считается вроде как UTF-16.


В винде за системную UTF-8, , что сделано для бинарной совместимости с ANSI а консоли там вообще две версии, причем старая по по дефолту все ещё 866 . А это две большие разницы...
Аватара пользователя
beria
постоялец
 
Сообщения: 103
Зарегистрирован: 29.09.2016 08:57:13

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

Сообщение Снег Север » 13.02.2017 19:42:11

Сколько мучений из-за изначально неверного решения...
Модуль LazUTF8Classes, LoadStringsFromFileUTF8 и SaveStringsToFileUTF8.
А компонент TFileNameEdit прекрасно работает с именами в пути в юникоде без каких-либо дополнительных телодвижений.
Аватара пользователя
Снег Север
энтузиаст
 
Сообщения: 897
Зарегистрирован: 27.11.2007 16:14:47

След.

Вернуться в Lazarus

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

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3

Рейтинг@Mail.ru
cron