Имя файла Lazarus ListBox SaveToFile со специальными символами

Я пишу приложение с Lazarus (1.5) fpc (3.1.1) для Windows XP/7/10. Мое приложение читает и записывает файлы в файловой системе по пути, выбранному пользователями. Если путь или имя файла содержат специальные символы (например, à è é), например:

C:\Users\ДеАндре\out.txt

Приложение вызывает исключение:

'EFCreateError' Невозможно создать файл "C:\Users\DeAndrè\out.txt".

Можно воспроизвести эту проблему, написав простое приложение с простой формой: перетащите в форму TListBox (ListBox1), два TButton (Button1 и Button2) и TSaveDialog (SaveDialog1).

В событии OnClick для Button1 (используется только для записи некоторых данных в ListBox1):

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Simple Add Hello to ListBox
  ListBox1.Items.Add('Hello '+IntToStr(ListBox1.Items.Count));
end; 

В событии OnClick Button2:

procedure TForm1.Button2Click(Sender: TObject);
begin
  if SaveDialog1.Execute then
  begin
    ListBox1.Items.SaveToFile(SaveDialog1.FileName);
  end;
end;  

Запустите приложение и нажмите кнопку «Button1» несколько раз (просто чтобы добавить несколько слов в список), затем нажмите кнопку «Button2» и попробуйте сохранить содержимое по пути, содержащему специальные символы...

Я заметил, что если я конвертирую FileName с помощью функции UTF8ToAnsi, это работает, но почему? Файловая система Windows не является UTF8?

Есть "стандартное" решение? например, настроить приложение для использования файловой системы в правильном режиме или аналогичном?

Спасибо


person AndreaBoc    schedule 17.05.2017    source источник
comment
@RudyVelthuis Спасибо, мои установки Windows используют файловую систему NTFS, согласно эта ссылка имеет кодировку Unicode   -  person AndreaBoc    schedule 17.05.2017
comment
Является ли код lazarus вызовом Unicode API   -  person David Heffernan    schedule 17.05.2017
comment
Тот же пример кода @David в Delphi (XE8) работает без ошибок...   -  person AndreaBoc    schedule 17.05.2017
comment
Да. Но дело не в этом. Использует ли код lazarus Unicode API.   -  person David Heffernan    schedule 17.05.2017
comment
Извините, комментарий не был закончен. Забудь об этом. И я уверен, что Lazarus (по умолчанию) использует API-интерфейсы ANSI, а не API-интерфейсы Unicode. Delphi XE8 использует UnicodeString по умолчанию, в то время как Lazarus использует (старый стиль) AnsiString по умолчанию, AFAIK.   -  person Rudy Velthuis    schedule 17.05.2017
comment
На самом деле ... есть дополнительная пользовательская опция, которую нужно добавить в компилятор для установки UnicodeAPI: EnableUTF8RTL, спасибо @Rudy и @David   -  person AndreaBoc    schedule 17.05.2017
comment
Windows API на самом деле использует либо ANSI, либо UTF-16, а не UTF-8. Я думаю, есть возможность использовать UTF-16, по крайней мере, в Windows. Но тогда вызываемые API также должны быть UTF-16 по умолчанию. В противном случае вам все равно понадобятся конверсии для каждого вызова API.   -  person Rudy Velthuis    schedule 17.05.2017
comment
@Rudy Библиотеки Lazarus могут конвертировать из UTF8 в UTF16 перед вызовом любого API. Это было бы совершенно разумно.   -  person David Heffernan    schedule 17.05.2017
comment
Как я уже сказал: вам понадобятся конверсии для каждого вызова API. Но я сомневаюсь, что это происходит. Исходники я не смотрел (пока), но меня бы это удивило. Я предполагаю, что они обычно используют API-интерфейсы Ansi. Это объяснило бы то, что было сказано в вопросе.   -  person Rudy Velthuis    schedule 19.05.2017
comment
@rudy Видимо, именно так и происходит. Это совершенно разумно.   -  person David Heffernan    schedule 20.05.2017
comment
@David: я никогда не говорил, что это неразумно. <грамм>   -  person Rudy Velthuis    schedule 20.05.2017


Ответы (1)


После указаний Руди и Дэвида я нашел решение: чтобы Lazarus мог использовать UnicodeAPI, вы должны добавить -dEnableUTF8RTL в «Custom Option»:

В «Проект» -> «Параметры проекта» -> «Дополнения и переопределение»

Нажмите «Добавить» -> «Пользовательский вариант» и «Добавить».

-dEnableUTF8RTL

Это заставляет компилятор использовать Unicode для доступа к файловой системе.

Также можно нажать на кнопку «Установить UTF8 в RTL». Эта кнопка в дополнение к -dEnableUTF8RTL добавляет опцию:

-FcUTF8

По этой ссылке форума Lazarus: http://forum.lazarus.freepascal.org/index.php?topic=27240.0 есть выдержка со страницы "Вики" о Lazarus и UTF8:

Обычно RTL использует системную кодовую страницу для строк (например, FileExists и TStringList.LoadFromFile). В Windows это кодировка, отличная от Unicode, поэтому вы можете использовать символы только из вашей языковой группы. LCL работает с кодировкой UTF-8, которая является полным диапазоном Unicode. В Linux и Mac OS X UTF-8 обычно является системной кодовой страницей, поэтому RTL использует здесь по умолчанию CP_UTF8.

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

person AndreaBoc    schedule 17.05.2017
comment
Вы можете принять свой собственный ответ (через два дня после его публикации), который поможет другим в будущем, - person Mawg says reinstate Monica; 07.04.2018