Lazarus utf8toconsole не работает

Содержание
  1. Русский язык в консольных приложениях Lazarus
  2. Lazarus utf8toconsole не работает
  3. Re: Иероглифы вместо русских букв.
  4. Re: Иероглифы вместо русских букв.
  5. Re: Иероглифы вместо русских букв.
  6. Re: Иероглифы вместо русских букв.
  7. Re: Иероглифы вместо русских букв.
  8. Re: Иероглифы вместо русских букв.
  9. Re: Иероглифы вместо русских букв.
  10. Re: Иероглифы вместо русских букв.
  11. Re: Иероглифы вместо русских букв.
  12. Re: Иероглифы вместо русских букв.
  13. Re: Иероглифы вместо русских букв.
  14. Re: Иероглифы вместо русских букв.
  15. Re: Иероглифы вместо русских букв.
  16. Работа с UTF8 в Lazarus 1.6
  17. Русский язык в консольных приложениях
  18. Unicode Support in Lazarus/ru
  19. Contents
  20. Введение
  21. RTL с кодовой страницей UTF-8 по умолчанию
  22. Использование
  23. Применение в Lazarus
  24. Использование UTF-8 в программах без LCL
  25. Вызов функций API, которые используют WideString или UnicodeString
  26. Чтение / запись текстового файла с кодовой страницей Windows
  27. Код, который очень сильно зависит от кодовой страницы Windows
  28. Запись в консоль
  29. Символы Юникода и кодовые точки в коде
  30. Функции кодовых точек для кодирования независимого кода
  31. Строковые литералы
  32. Присвоение строковых литералов различным типам строк
  33. Без <$codepage utf8>или переключателя компилятора -FcUTF8
  34. С <$codepage utf8>или переключателем компилятора -FcUTF8
  35. Переход из более старых версий Lazarus + LCL
  36. Техническая реализация
  37. Кодовые страницы FPC
  38. Открытые вопросы
  39. Вызовы функций WinAPI в библиотеках FPC
  40. Будущее
  41. Что насчет режима DelphiUnicode?
  42. Как насчет ModeSwitch UnicodeStrings?
  43. Почему бы не использовать UTF8String в Lazarus?
  44. Почему UTF8String показывает странные символы, а String работает
  45. Что случится, если я использую <$codepage utf8>?
  46. См. также

Русский язык в консольных приложениях Lazarus

Наверняка вы уже знаете, что с определённого времени редактор исходного кода Lazarus по умолчанию работает в кодировке UTF8. Это не страшно, если вы создаёте приложения с графическим интерфейсом, либо консольные приложения с выводом на английском языке.

Но! Всё меняется, когда вы пытаетесь вывести в консоль Windows русские буквы. Вместо русских символов выводятся “краказябры”. И это реально бесит.

Происходит это потому, что в редакторе исходного кода Lazarus символы имеют кодировку UTF8, а консоль Windows (во всяком случае, в Windows версии до XP включительно, и в “семёрке” по моему тоже) имеет другую кодировку (обычно CP866, хотя может быть и другая).

Поэтому консоль не понимает, какие символы ей надо выводить. В итоге мы видим злополучные “краказябры” (см. рис.).

Русский язык в Lazarus — это давняя беда, которая мучает всех программистов, а особенно — начинающих. Об одном из решений я этого вопроса рассказывал здесь. Это решение рабочее, но не всегда приемлемое. К тому же оно может сыграть с вами злую шутку, когда при повторном открытии проекта вместо комментариев и других русских букв в исходных кодах вы увидите всё те же “краказябры”.

Поэтому сегодня я расскажу ещё об одном решении. Оно тоже не идеально, но в некоторых случаях может пригодиться.

Итак, для того, чтобы в консоль Windows выводились правильно русские символы, я предлагаю использовать функцию UTF8ToConsole, которая преобразует строку в кодировке UTF8 в кодировку, которая используется консольными приложениями Windows по умолчанию.

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

Но, есть одно “но”. И даже не одно, а два.

Во-первых, функция UTF8ToConsole находится в модуле LazUTF8. Соответственно, вам этот модуль надо подключить к своей программе (надо сказать, что эта функция есть и в других модулях, например, в модуле FileUtil, но я советую использовать LazUTF8, потому что в нём есть и другие полезные функции для работы с UTF8).

А во-вторых, вам надо будет выполнить следующие действия:

  • В главном меню выбрать ПРОЕКТ — ИНСПЕКТОР ПРОЕКТА — КНОПКА ДОБАВИТЬ (+) — НОВАЯ ЗАВИСИМОСТЬ
  • В открывшемся окне в списке выбрать LCL и нажать кнопку СОЗДАТЬ НОВУЮ ЗАВИСИМОСТЬ
  • Закрыть окно инспектора объектов.

Если что-то непонятно, то см. видео выше.

После этого все строки с русскими символами, которые должны выводиться в консоль, в исходном коде надо записывать так:

WriteLn(UTF8ToConsole(‘Это текст, который состоит из русских букв.’));

Итог см. на рисунке:

Но! Снова эти “но”.

В некоторых случаях этот способ может не сработать (зависит от настроек операционной системы и некоторых других обстоятельств — я не стал разбираться в причинах).

Если вы сделали всё, что здесь описано, но русские буквы всё-равно не выводятся правильно, то попробуйте изменить шрифт в консоли (правая кнопка по заголовку — свойства — шрифт). Выберите шрифт Lucida Console. Если не знаете, как это сделать, то см. видео о свойствах консоли здесь.

У меня, например, на ноутбуке этот способ работает нормально со всеми шрифтами. А на рабочем компьютере русские буквы правильно отображаются только если выбрать шрифт Lucida Console.

Для учебных программ это не проблема — измените свойства для окна (поменяйте шрифт) и всё.

Но вот если вы вдруг будете распространять свою программу, то вам, конечно, надо бы знать наверняка, что этот способ сработает, или хотя бы постараться сделать так, чтобы при запуске программы устанавливался нужный шрифт.

Сделать это можно, но это уже другая история.

Источник

Lazarus utf8toconsole не работает

Paster Fob » 11.05.2011 20:19:45

Ну вот установил Lasarus,попробовал написать что-нибудь,но вместо русских букв какие-то иероглифы.Вот к примеру.

Почему так,или что-то надо настроить?

Re: Иероглифы вместо русских букв.

Nik » 11.05.2011 20:29:55

Скорее всего в консоли не поддерживается UTF8. Попробуйте вывести как-то так:

Re: Иероглифы вместо русских букв.

Ism » 11.05.2011 20:30:33

или чтото такое для Dos кодировки

Re: Иероглифы вместо русских букв.

Mr.Smart » 11.05.2011 20:31:39

Re: Иероглифы вместо русских букв.

Paster Fob » 11.05.2011 20:42:10

Re: Иероглифы вместо русских букв.

Paster Fob » 14.05.2011 06:02:03

Re: Иероглифы вместо русских букв.

v-t-l » 14.05.2011 09:42:52

Re: Иероглифы вместо русских букв.

Paster Fob » 14.11.2012 18:40:30

Re: Иероглифы вместо русских букв.

mtdu » 14.11.2012 20:57:16

Re: Иероглифы вместо русских букв.

SSerge » 15.11.2012 04:51:20

Следующий вопрос предвижу » почему это у меня не работают функции copy, delete, insert и вместо i-го символа строки получается какая-то хрень, а длина строки из трех русских букв почему равна шести ?»

*подумал* и решил таки рекомендовать:

http://www.freepascal.ru/article/freepa . 718142000/ — «Правильный» путь развития, по работе с русским языком, особенно в консоли, противоречащий 99% учебников по FreePascal, Pascal и Deplhi

И, «прикладная кадаврология», http://sirserge.altai.info/articles/?id=41 о том, как работать с русским языком «по старому пути развития», ведущему в тупик. Беллетристику аккуратно пропускаем мимо ушей, стиль написания там чернушный.

смотрите сами, стоит эти материалы применять или нет, написаны они отнюдь не для начинающих

Re: Иероглифы вместо русских букв.

Paster Fob » 15.11.2012 06:35:11

Re: Иероглифы вместо русских букв.

SSerge » 15.11.2012 07:36:56

Иллюстрация «старого подхода».
Внимание. Lazarus должен быть исключительно «официальный», релизный , функции преобразования в так называемых «последних» версиях на компиляторе 2.7.1 обычно испорчены до необратимого состояния. Файл — в кодировке UTF8.

Код: Выделить всё program project1;
Uses FileUtil;

begin
s1:=’Введите предложение:’;
write(UTF8ToConsole(s1));
readln(s2);
s2:=ConsoleToUTF8(s2);
s3:=’Вы ввели:’;
writeln(UTF8ToConsole(s3),UTF8ToConsole(s2));
end.

. вообще то лазарус не предназначен для работы с консолью.

Re: Иероглифы вместо русских букв.

Paster Fob » 15.11.2012 08:06:03

SSerge писал(а): Иллюстрация «старого подхода».
Внимание. Lazarus должен быть исключительно «официальный», релизный , функции преобразования в так называемых «последних» версиях на компиляторе 2.7.1 обычно испорчены до необратимого состояния. Файл — в кодировке UTF8.

Код: Выделить всё program project1;
Uses FileUtil;

begin
s1:=’Введите предложение:’;
write(UTF8ToConsole(s1));
readln(s2);
s2:=ConsoleToUTF8(s2);
s3:=’Вы ввели:’;
writeln(UTF8ToConsole(s3),UTF8ToConsole(s2));
end.

. вообще то лазарус не предназначен для работы с консолью.

Re: Иероглифы вместо русских букв.

SSerge » 15.11.2012 08:20:19

FreePascal какой? Должен быть 2.6.0

Добавлено спустя 5 минут 24 секунды:
что то не обратил внимание. У вас собственно что вводится, то и выводится, без искажений. Очень подозреваю ненормальные настройки консоли в рамках Windows (русификаторы какие нибудь и т.п.) Во всяком случае, русские буквы должны печататься как рксские буквы, когда вы их набираете, это к lazarus/freepascal отношения не имеет, это настройки и функции вашей операционной системы

Добавлено спустя 1 минуту 4 секунды:
Как до консоли добираетесь?

Источник

Работа с UTF8 в Lazarus 1.6

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Установка ZEOS в Lazarus, работа с PostgressSQL в Lazarus
Не получается никак установить компонент ZEOS в Lazarus открываю пакет с Zeos, нажимаю.

Работа со строками Utf8
Нужно строку в кодировке Utf8 вывести в консоль по 10 символов, в строке могут быть как буквы.

Правильная работа с utf8 строками
какой самый рассово-верный способ манипулирования строками в utf8. Я пробовал обойтись use utf8;.

Работа с 1С в Lazarus 1.2.0
Доброе время суток! Пытаюсь подключиться к 1С в Lazarus 1.2.0 c помощью COM. Подключение.

Could not connect with connection string «DRIVER=;UID=*myuid*;PWD=*mypass*;UID=*myuid*;UserCommitSync =Yes;Threads=3;SafeTransactions=0;PageTimeout=5;MaxScanRows= 8;MaxBufferSize=2048;FIL=MS Access; DriverId=25; DefaultDir=; DBQ=D:\*path*\base\base.mdb;». ODBC error details: LastReturnCode: SQL_ERROR; Record 1: SqlState: HY024; NativeError: -1023; Message: [Microsoft][������� ODBC Microsoft Access] ������ ‘(��� ������)’ ������ ��������� ����. ���������, ��� ���� ����� ��������� � ������� ����������� � �������, �� ������� ��������� �����.;.

Press OK to ignore and risk data corruption.
Press Cancel to kill the program.

В Lazarus 1.4.4 все нормально работает.

UPD. Пробелы в цитате запроса добавил, чтобы смайлики не отображались.

Добавлено через 21 минуту
UPD2.
Странно, сохранил строку подключения к БД в файл — всё корректно отображается. Никаких вопросов и кракозябр. Открывал в блокноте.

Добавлено через 5 минут
UPD3.
Поместил БД по адресу, в котором нет кириллицы, подключение произошло успешно. Но в запросах вместо русских букв возвращаются знаки вопросов. Повторюсь, в Lazarus 1.4.4 такого не было.

Работа с файлами на Lazarus
В файле f записаны целые числа. Написать программу, которая в файл g записывает четные числа, а.

Работа со списками Lazarus, Delphi
Список строк заполняется вручную или из текстового файла. После этого разрешается набор букв в поле.

Работа с текстом и файлами в lazarus
Задача заключается в следующем:нужно открыть некий файл в котором есть текс,взять оттуда этот текст.

Работа со сканером штрихкодов в Lazarus
Собственно задача стоит такая: 1) сканировать штрихкод товара 2) сравнивать его с имеющимися в.

Работа с регулярными выражениями в Lazarus
Уважаемые, скажите пожалуйста, как в Lazarus организовать работу с регулярными выражениями? .

Источник

Русский язык в консольных приложениях

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Русский язык в консольных приложениях
Какая то фигня. Добился русского языка при вводе и выводе настройками компилятора <$mode.

Русский язык в консольных приложениях!
Здравствуйте форумчане, у меня возник такой вопрос, вообщем когда я вывожу командой cout то русские.

Ошибка в консольных приложениях
Все привет Как получить последнюю ошибку в консоль. приложениях а то при ошибке оно сразу.

Графика в консольных приложениях WIN32
Всем привет))) Может тупой вопрос но оч надо узнать, как работать с простой графикой на новых.

ValentinNemo,
Если задано <$codepage utf8>, то string компилируется как UnicodeString со всеми сопутствующими «сюрпризами».

Добавлено через 17 минут
volvo,
С некоторых пор это уже не так.

bormant, я проверил string и UnicodeString. Вводится и выводится кириллица хорошо в обоих случаях, а вот классические процедуры и функции для работы со строками работают по разному.

Протокол работы программы

Привет на русском языке
рив
Напишите что-нибудь на кириллице:
жвдлжыдлажыдаыжда
Вот что выводится: жвдлжыдлажыдаыжда
вдл

Протокол работы программы

Привет на русском языке
?р
Напишите что-нибудь на кириллице:
далыодалыоад
Вот что выводится: далыодалыоад
алы

Ваш код не работает на Win7

Добавлено через 1 минуту
По моему мнению, лучший вариант будет этот:

Отображение русского языка в консольных приложениях
Решил поэксперементировать с консольными приложениями в делфи.Но встретил проблему неотоброжается.

Еще о консольных приложениях в VB — переназначение В/Выв
Кто может подсказать пример консольного приложения на VB, которое бы корректно обрабатывало.

Как рисовать в консольных приложениях? Нужна помощь
Здравствуйте. Как можно рисовать в консольных приложениях используя с++? НЕ VISUAL с++. Если можно.

Обмен данными между процессами в консольных приложениях
Привет. Можно ли как — то обмениваться данными между двумя запущенными консольными приложениями без.

Источник

Unicode Support in Lazarus/ru

Contents

Введение

Здесь описывается поддержка Unicode в «программах» Lazarus (консольных или серверных, без графического интерфейса) и «приложениях» (GUI с использованием LCL) при использовании особенностей FPC 3.0+.

Решение является кросс-платформенным и использует кодировку UTF-8, которая отличается от UTF-16 Delphi, но вы можете написать код, полностью совместимый с Delphi на уровне исходного кода, запомнив лишь несколько правил.

Поддержка Unicode включается автоматически для приложений LCL начиная с Lazarus 1.6.0 при компиляции с FPC 3.0+.

Старый метод поддержки UTF-8 в LCL при использовании FPC версий до 2.6.4 включительно, описан здесь: LCL Unicode Support

RTL с кодовой страницей UTF-8 по умолчанию

По умолчанию RTL использует системную кодовую страницу для AnsiStrings (в таких операциях, как например FileExists и TStringList.LoadFromFile). Под Windows это не-Unicode кодировка, поэтому могут использоваться только символы из текущей языковой группы (не более 256 символов). LCL, с другой стороны, работает с кодировкой UTF-8, охватывающей весь диапазон Unicode. Под Linux и macOS UTF-8 обычно является системной кодовой страницей, и здесь RTL использует по умолчанию CP_UTF8.

FPC, начиная с версии 3.0, обеспечивает API для изменения кодовой страницы RTL по умолчанию на другое значение. Lazarus (конкретно пакет LazUtils) использует данный API и изменяет кодовую страницу RTL по умолчанию на UTF-8 (CP_UTF8). Это означает, что пользователи Windows также могут теперь использовать строки UTF-8 в RTL.

  • Например, FileExists и StringList.LoadFromFile(Filename) теперь имеют полную поддержку Unicode. См. Полный перечень функций, которые полносттью поддерживают Unicode, здесь:
  • AnsiToUTF8, UTF8ToAnsi, SysToUTF8, UTF8ToSys не работают (не изменяют передаваемых данных). Эти функции обычно использовались для упомянутых выше функций RTL, которые больше не нуждаются в преобразованиях. Относящееся к функциям WinAPI, см ниже.
  • Многочисленные вызовы UTF8Encode и UTF8Decode больше не требуются, потому что такие действия при присваивании значений UnicodeString переменным типа String и наоборот компилятор делает автоматически.
  • При работе с WinAPI необходимо использовать «W»-функции или пользоваться функциями UTF8ToWinCP и WinCPToUTF8. То же верно для библиотек, которые до сих пор используют Ansi WinAPI функции. Например, в FPC 3.0 и более ранних версиях в этом нуждается unit registry.
  • «String» и «UTF8String» — различные типы. Если вы присваиваете значение String переменной типа UTF8String, компилятор добавляет код для проверки совпадения кодировок. Это будет стоить дополнительного времени исполнения и увеличит размер кода. Просто используйте String вместо UTF8String.
  • Консоль Windows использует кодировку, которая может отличаться от системной (в случае русского языка это всегда именно так). writeln в FPC 3.0+ автоматически преобразует строки UTF-8 в кодовую страницу консоли. Некоторые консольные программы Windows ожидают на входе строки в кодировке консоли и результаты своей работы также выдают в кодовой странице консоли. Для соответствующего преобразования можно использовать функции UTF8ToConsole и ConsoleToUTF8.

Дополнительная информация о новинках поддержки Unicode в FPC: FPC Unicode support

Использование

Следуйте простым правилам:

  • Используйте как обычно тип «String» вместо UTF8String или UnicodeString.
  • Всегда присваивайте константу переменной типа String.
  • Используйте тип UnicodeString явно для вызовов API, когда это необходимо.

Эти правила делают большую часть кода уже совместимым с Delphi при использовании настроек проекта по умолчанию.

Применение в Lazarus

Новый режим включается автоматически при компиляции FPC 3.0+. Это поведение может быть отключено директивой компиляции -dDisableUTF8RTL, детали см. на странице Lazarus with FPC3.0 without UTF-8 mode.

Если вы используете строковые литералы в новом режиме, ваши исходники всегда должны быть в кодировке UTF-8. Однако, ключ -FcUTF8 на самом деле обычно не требуется. Дополнительные сведения приведены ниже, в разделе «Строковые литералы».

Что же на самом деле происходит в новом режиме? В секции предварительной инициализации вызываются две FPC функции, устанавливающие кодировку строк по умолчанию в исполняющих библиотеках FPC в UTF-8 :

Кроме того, функции UTF8. () из LazUTF8 (LazUtils) устанавливаются в качестве функций обратного вызова для функций RTL, имена которых начинаются с Ansi. ().

Использование UTF-8 в программах без LCL

В не LCL-проекте добавьте зависимость для пакета LazUtils. Затем добавьте модуль LazUTF8 в секцию uses основного файла программы. Он должен быть в начале, сразу после критических менеджеров памяти и многопоточности (например, cmem, heaptrc, cthreads).

Вызов функций API, которые используют WideString или UnicodeString

Если тип параметра WideString или UnicodeString, вы можете просто передать ему строку. Компилятор преобразует данные автоматически. Появится предупреждение о преобразовании из AnsiString в UnicodeString, которое можно либо проигнорировать, либо подавить, приведя тип String к UnicodeString.

Переменная S в приведенных ниже примерах определяется как String, что здесь означает AnsiString.

Когда тип параметра является указателем PWideChar, вам нужна временная переменная UnicodeString. Присвойте ей свою строку. Затем компилятор преобразует эти данные. Затем введите временную переменную в PWideChar.

Примечание: в обоих случаях код совместим с Delphi. Это означает, что вы можете скопировать/вставить его в Delphi, и он сработает на 100% правильно. В Delphi String проецируется в UnicodeString.

Типичным случаем является вызов Windows API. Только должны вызываться их версии «W», потому что они поддерживают Unicode. Обычно используйте UnicodeString также с Windows API. WideString необходим только при программировании COM/OLE, где ОС заботится об управлении памятью.

Чтение / запись текстового файла с кодовой страницей Windows

Это не совместимо ни с Delphi, ни с прежним кодом Lazarus. На практике вы должны инкапсулировать код, связанный с системной кодовой страницей, и преобразовать данные в UTF-8 как можно быстрее.

Либо используйте RawByteString и сделайте явное преобразование.

. или установите правильную кодовую страницу для существующей строки

Примечание: в строковой переменной должен быть какой-то текст. Пустая строка на самом деле является указателем Nil, и вы не можете установить ее кодовую страницу.

Windows.GetACP() возвращает системную кодовую страницу Windows.

Код, который очень сильно зависит от кодовой страницы Windows

Существует «план B» для кода, который очень сильно зависит от системной кодовой страницы Windows или должен записываться в консоль Windows за пределами кодовой страницы консоли.
См.: Lazarus с FPC3.0 без режима UTF-8.
К счастью, это нужно нечасто. В большинстве случаев проще конвертировать данные в UTF-8.

Запись в консоль

Вывод консоли Windows работает корректно, если ваши символы принадлежат кодовой странице консоли. Например, символ для рисования рамки '╩' в кодовой странице CP437 составляет один байт #202 и часто используется так:

Когда вы конвертируете код в UTF-8, например, используя пункт всплывающего меню редактора исходного кода Lazarus File Settings (Параметры файла) / Encoding (Кодировка) / UTF-8, и нажимая кнопку диалога «Change file on disk» (Изменить файл на диске), символ '╩' становится 3-х байтным (#226#149#169), поэтому литерал становится строкой.

Процедуры write и writeln преобразуют строку UTF-8 в текущую кодовую страницу консоли. Таким образом, ваша консольная программа теперь выводит '╩' в Windows с любой кодовой страницей (т.е. не только с CP437), и она даже работает в Linux и macOS. Вы также можете использовать '╩' в строках LCL, например, Memo1.Lines.Add('╩');

Если ваши символы не принадлежат кодовой странице консоли, все усложняется. Тогда вы вообще не сможете использовать новую систему Unicode.
См.: Проблема Системной кодировки и Консольной кодировки (Windows)

Символы Юникода и кодовые точки в коде

Функции кодовых точек для кодирования независимого кода

В пакете LazUtils есть модуль LazUnicode со специальными функциями для работы с кодовыми точками, независимо от кодировки. Они используют функции UTF8. () из LazUTF8 при использовании в режиме UTF-8, и функции UTF16. () из LazUTF16 при использовании в <$ModeSwitch UnicodeStrings>FPC или в Delphi (да, Delphi поддерживается!).

В настоящее время <$ModeSwitch UnicodeStrings>можно протестировать, задав «UseUTF16». Также есть тестовая программа LazUnicodeTest в каталоге components/lazutils/test. Она имеет 2 режима сборки, UTF8 и UTF16, для удобства тестирования. Тестовая программа также поддерживает Delphi, тогда, очевидно, используется режим UTF-16.

LazUnicode позволяет одному исходному коду работать между:

  • Lazarus с его UTF-8 решением.
  • Будущие FPC и Lazarus с Delphi-совместимым решением UTF-16.
  • Delphi, где String = UnicodeString.

Это обеспечивается перечисленными ниже функциями, не зависящим от кодирования:

  • CodePointCopy() — аналогична UTF8Copy()
  • CodePointLength() — аналогична UTF8Length()
  • CodePointPos() — аналогична UTF8Pos()
  • CodePointSize() — аналогична UTF8CharacterLength() (функция устарела. Вместо нее используйте UTF8CodepointSize. См. подробнее)
  • UnicodeToWinCP() — аналогична UTF8ToWinCP()
  • WinCPToUnicode() — аналогична WinCPToUTF8()

Этот режим также предоставляет перечислитель для кодовых точек, который компилятор использует для цикла for-in. В результате, независимо от кодировки, этот код работает:

Delphi не предоставляет аналогичные функции для CodePoints в своем решении UTF-16. Практически большая часть кода Delphi рассматривает UTF-16 как кодировку с фиксированной шириной, что привело к возникновению большого количества неработающего кода UTF-16. Это означает, что использование LazUnicode также для Delphi улучшит качество кода!

Для использования Delphi необходимы оба модуля LazUnicode и LazUTF16.

Строковые литералы

Исходный код должен сохраняться в кодировке UTF-8. Lazarus создает такие файлы по умолчанию. Вы можете изменять кодировку импортированных файлов, щелкая правой кнопкой мыши в редакторе исходного кода / File Settings (Настройки файла) / Encoding (Кодировка).

Обычно директива <$codepage utf8>/ -FcUTF8 не требуется. Это довольно нелогично, поскольку значение этого флага заключается в обработке строковых литералов как UTF-8. Однако новый режим UTF-8 переключает кодирование во время выполнения, а константы оцениваются во время компиляции.

Таким образом, без -FcUTF8 компилятор (ошибочно) считает, что строковая константа кодируется системной кодовой страницей. Затем он видит переменную String с кодировкой по умолчанию (которая будет изменена на UTF-8 во время выполнения, но компилятор этого не знает). Таким образом, то же для кодировки по умолчанию, преобразование не требуется, компилятор с радостью копирует символы, и все идет хорошо, в то время как на самом деле его дважды обманывали в течение процесса.

По правилу шаловливых ручек, используйте тип «String» и заставляйте литералы работать.

Примечание: Строка UTF-8 может состоять из чисел, как это продемонстрировано для s2.

  • Литералы AnsiString/String работают как с директивой <$codepage utf8>/ -FcUTF8 , так и без неё.
  • Литералы ShortString работоспособны только без указания директивы <$codepage utf8>/ -FcUTF8. Вы можете сделать следующее:

В качестве альтернативы, возможно использовать строки shortstring с включенной директивой $codepage путем прямого присвоения кодов символов:

  • WideString/UnicodeString/UTF8String работают только с<$codepage utf8>/ -FcUTF8.

Присвоение строкового литерала другим строковым типам, кроме простого «String», более мудрено. Смотрите таблицы, что работает, а что нет.

Присвоение строковых литералов различным типам строк

Здесь работает означает правильную кодовую страницу и правильные кодовые точки. Кодовая страница 0 или кодовая страница 65001 — обе являются правильными, они означают UTF-8.

Без <$codepage utf8>или переключателя компилятора -FcUTF8

Тип String, исходник в UTF-8 Пример Const (в исходнике) Присвоение String Присвоение UTF8String Присвоение UnicodeString Присвоение CP1252String Присвоение RawByteString Присвоение ShortString Присвоение PChar
const const s = ‘äöü’; working working wrong wrong wrong working working working
String const s: String = ‘äöü’; working working working working working working working working
ShortString const s: String[15] = ‘äöü’; working working working working wrong encoded working working not available
UTF8String const s: UTF8String = ‘äöü’; wrong wrong wrong wrong wrong wrong wrong wrong
UnicodeString const s: UnicodeString = ‘äöü’; wrong wrong wrong wrong wrong wrong wrong wrong
String с объявленной кодовой страницей type CP1252String = type AnsiString(1252); wrong wrong wrong wrong wrong wrong wrong wrong
RawbyteString const s: RawbyteString = ‘äöü’; working working working working to codepage 0 changed working working working
PChar const c: PChar = ‘äöü’; working working working working wrong working working working

С <$codepage utf8>или переключателем компилятора -FcUTF8

Тип String, исходник в UTF-8 Пример Const (в исходнике) Присвоение String Присвоение UTF8String Присвоение UnicodeString Присвоение CP1252String Присвоение RawByteString Присвоение ShortString Присвоение PChar
const const s = ‘äöü’; UTF-16 encoded working working working working working working working
String const s: String = ‘äöü’; working working working working working working working working
ShortString const s: String[15] = ‘äöü’; wrong wrong wrong wrong wrong wrong wrong not available
UTF8String const s: UTF8String = ‘äöü’; working working working working working working working working
UnicodeString const s: UnicodeString = ‘äöü’; working working working working working working working wrong
String с объявленной кодовой страницей type CP1252String = type AnsiString(1252); working working working working working working wrong wrong
RawbyteString const s: RawbyteString = ‘äöü’; working working working working to codepage 0 changed working working working
PChar const c: PChar = ‘äöü’; wrong wrong wrong wrong wrong wrong wrong wrong

Помните, что присваивание между переменными разных типов строк всегда работает благодаря их динамическому кодированию в FPC 3+. Данные конвертируются автоматически при необходимости.
Только строковые литералы являются проблемой.

Переход из более старых версий Lazarus + LCL

Ранее (до 1.6.0) LCL поддерживал Unicode с выделенными функциями UTF8. Код не был совместим с Delphi.

Сейчас многие старые приложения LCL продолжают работать без изменений. Однако имеет смысл очистить код, чтобы сделать его более простым и более совместимым с Delphi. Код, который читает/записывает данные с использованием кодировки системной кодовой страницы Windows, нарушается и должен быть изменен. (См. Чтение / запись текстового файла с кодовой страницей Windows).

Явные функции преобразования необходимы только для ввода-вывода с данными кодовой страницы Windows или при вызове функций Windows Ansi. В противном случае FPC позаботится о автоматическом преобразовании кодировок. Для преобразования вашего старого кода предусмотрены пустые функции преобразования.

  • UTF8Decode, UTF8Encode — Почти все можно удалить.
  • UTF8ToAnsi, AnsiToUTF8 — Почти все можно удалить.
  • UTF8ToSys, SysToUTF8 — Почти все можно удалить. Теперь они являются пустышками и возвращают только свои параметры.

Файловые функции в RTL теперь заботятся о кодировке имен файлов. Все (?) связанные с именем файла функции . UTF8() можно заменить на Delphi-совместимую функцию без суффикса UTF8. Например, FileExistsUTF8 можно заменить на FileExists.

Большинство строковых функций UTF8. () можно заменить на совместимые с Delphi функции Ansi. (). Например, UTF8UpperCase() -> AnsiUpperCase().

Теперь Unicode работает и в программах без GUI. Требуется только зависимость от LazUtils и размещение модуля LazUTF8 в разделе uses основного файла программы.

Для исторической справки, это была старая поддержка Unicode в LCL: Old LCL Unicode Support

Техническая реализация

Что на самом деле происходит в системе Unicode? Эти 2 функции FPC вызываются в разделе ранней инициализации, устанавливая кодировку String по умолчанию в FPC в UTF-8:

В Windows функции UTF8. () в LazUTF8 (LazUtils) устанавливаются в качестве бэкэндов для строковых функций RTL Ansi. (). Таким образом, эти функции работают совместимым с Delphi способом.

Кодовые страницы FPC

Компилятор (FPC) поддерживает указание кодовой страницы, которое может быть записано через опцию командной строки -Fc (т.е. -Fcutf8) или эквивалентную директиве codepage (т.е. ). В этом случае, перед тем, как копировать байты, представляющие строковые константы в тексте вашей программы, компилятор будет интерпретировать все символьные данные в соответствии с указанной кодовой страницей. Есть две вещи, которые не стоит упускать из виду:

  • На платформах Unix, менеджер широких строк должен быть обязательно включен добавлением юнита cwstring в перечень uses. Без него программа не сможет правильно преобразовывать строковые данные во время исполнения.

Менеджер широких строк добавляется по умолчанию в новом режиме UTF-8 RTL, однако это делает программу зависимой от libc и усложняет кросс-компиляцию.

  • Компилятор преобразует все строковые константы, содержащие символы, не относящиеся к ASCII, в константы типа widestring. Затем они автоматически преобразуются обратно в ansistring (либо во время компиляции, либо во время исполнения), но это может привести к искажениям, если вы попытаетесь смешать в одной строковой константе символы, напечатанные в тексте исходника и символы, заданные числовым представлением:

После компиляции и исполнения программа выведет:

Причина в том, что после того как в строке обнаружен символ ä, как упоминалось выше, оставшаяся часть строковой константы, присваиваемой переменной ‘c’, будет обработана как widestring. В результате #$C3 и #$A4 интерпретируются как widechar(#$C3) и widechar(#$A4), вместо прямой трансляции в байтовое представление.

Открытые вопросы

  • Символьные переменные в TFormatSettings (баг 27086): например: ThousandSeparator, DecimalSeparator, DateSeparator, TimeSeparator, ListSeparator. Эти поля должны быть заменены на строки для корректной поддержки UTF-8. Например, под Linux с установками LC_NUMERIC=ru_RU.utf8 разделитель тысяч состоит из двух байт nbsp/160.
    • Обход проблемы: использовать только одиночные символы пробелов вместо того, что должно быть на самом деле, как это сделано в патче на баг 27099

Вызовы функций WinAPI в библиотеках FPC

  • Unit registry, TRegistry — этот unit использует Ansi функции Windows API и поэтому вам придётся пользоваться UTF8ToWinCP, WinCPToUTF8. Раньше для этого требовался вызов UTF8ToSys.
  • Все вызовы Windows функций с Ansi API в библиотеках FPC должны быть заменены версией W-API. Это в любом случае будет сделано для будущей поддержки UTF-16, поэтому никакого конфликта интересов нет. (прим. перев. — однако, эти действия означают декларированный отказ от дальнейшей поддержки версий Windows с неполной поддержкой Unicode — Windows 98, 95 и более ранних, а также некоторых мобильных и встроенных)
  • TProcess — под Windows TProcess FPC 3.0 поддерживает только системную кодовую страницу. Необходимо либо использовать TProcessUTF8 из unit utf8process или патчить FPC, см. баг 29136

ToDo: Перечислить все относящиеся к багтрекеру FPC проблемы и патчи, которые могут эти проблемы решить.

Будущее

Целью проекта FPC является создание решения, базирующегося на Delphi-совместимом UnicodeString (UTF-16), но пока мы к этому не готовы. Потребуется длительное время для такой реализации.

Реализацию LCL на базе UTF-8 в её имеющемся виде необходимо рассматривать как временное решение. В будущем, когда в FPC будет полная поддержка UnicodeString как в RTL, так и в FCL, проект Lazarus обеспечит решения для LCL, использующее эти возможности. В то же время целью является и сохранение поддержки UTF-8, несмотря на то, что это может потребовать изменения в строковых типах или чего-то ещё. Деталей пока не знает никто. Мы обязательно сообщим вам о них, когда станет известно.

В сущности, LCL скорее всего придётся в будущем разделиться на две версии — одну для UTF-8, и другую для UTF-16.

Что насчет режима DelphiUnicode?

был добавлен в FPC 2.7.1 и похож на с . Смотрите следующий вопрос о ModeSwitch UnicodeStrings.

Как насчет ModeSwitch UnicodeStrings?

был добавлен в FPC 2.7.1 и определяет «String» как «UnicodeString» (UTF-16), «Char» как «WideChar», «PChar» как «PWideChar» и так далее. Это влияет только на текущий модуль. Другие модули, в том числе используемые этим модулем, имеют свое собственное определение «String». Многие строки и типы RTL (например, TStringList) используют 8-битные строки, которые требуют преобразования из/в UnicodeString, которые автоматически добавляются компилятором. LCL использует строки UTF-8. Рекомендуется использовать исходники в кодировке UTF-8 с или без «-FcUTF8».

Почему бы не использовать UTF8String в Lazarus?

Кратко: потому что FCL не использует его.

Исчерпывающе: UTF8String определен в модуле system как

Компилятор всегда предполагает, что он имеет кодировку UTF-8 (CP_UTF8), которая является многобайтовой кодировкой (то есть 1-4 байта на кодовую точку). Обратите внимание, что оператор [] обращается к байтам, а не к символам или кодовым точкам. То же самое для UnicodeString, но только слова вместо байтов. С другой стороны, предполагается, что String во время компиляции имеет DefaultSystemCodePage (CP_ACP). DefaultSystemCodePage определяется во время выполнения, поэтому компилятор консервативно полагает, что String и UTF8String имеют разные кодировки. Когда вы присваиваете или комбинируете String и UTF8String, компилятор вставляет код преобразования. То же самое для ShortString и UTF8String.

Lazarus использует FCL, который использует String, поэтому использование UTF8String добавит конверсии. Если DefaultSystemCodePage не UTF-8, вы теряете символы. Если это UTF-8, то нет смысла использовать UTF8String.

UTF8String станет полезным, когда в конце концов появится FCL UTF-16.

Почему UTF8String показывает странные символы, а String работает

Вопрос: это ошибка? Ответ: Нет, потому что это работает как задокументировано.

FPC игнорирует переменную LANG для создания в каждой системе одинакового результата. По историческим причинам/Delphi-совместимости он использует ISO-8859-1 по умолчанию. Lazarus предпочитает UTF-8.

  • Исходники UTF-8 работают со String, потому что
    1. FPC по умолчанию не добавляет код преобразования для обычных строковых литералов.
    2. Исходная кодовая страница равна кодовой странице времени выполнения. В Windows LazUTF8 устанавливает значение CP_UTF8.
  • UTF8String требует исходников UTF-8. Начиная с FPC 3.0 для UTF8String вы должны сообщать компилятору, что исходник является UTF8 (-FcUTF8, или сохранять файл как UTF-8 с BOM).

Примечание: Если вы сообщаете компилятору исходную кодировку UTF-8, он заменяет все строковые литералы ASCII этого модуля на UTF-16, увеличивая размер двоичного файла, добавляя некоторые служебные данные, и PChar для литералов требует явного преобразования. Вот почему Lazarus не добавляет его по умолчанию.

Что случится, если я использую <$codepage utf8>?

FPC имеет очень ограниченную поддержку UTF-8. Фактически, FPC поддерживает хранение литералов только как 8-битные строки с кодировкой «по умолчанию» или как widestrings (широкие строки). Поэтому любая кодовая страница не по умолчанию преобразуется в widestrings, даже если это системная кодовая страница. Например, большинство Linux/Mac/BSD используют UTF-8 в качестве системной кодовой страницы. Передача -Fcutf8 в компилятор сохранит строковый литерал как widestrings.

Во время выполнения widestring литерал конвертируется. Когда вы присваиваете литерал AnsiString, widestring литерал преобразуется с помощью widestringmanager в кодировку системы. По умолчанию widestringmanager под Unix просто конвертирует widechars в символы, уничтожая любые символы не ASCII. Вы должны использовать widestringmanager, например, cwstring, чтобы получить правильное преобразование. Модуль LazUTF8 делает это.

См. также

Информация о Unicode, кодовых страницах, строковых типах и RTL в FPC.
Обратите внимание, что эта информация не совсем полезна для системы Lazarus UTF-8, потому что с точки зрения FPC она является хаком и меняет кодовую страницу по умолчанию.
Поддержка Юникода в FPC

Источник

Читайте также:  Амазфит бип как настроить уведомления
Оцените статью