[Решено] Запись файлов юникодом и не только

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

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

[Решено] Запись файлов юникодом и не только

Сообщение Risto » 10.03.2016 11:57:37

Собственно, имеется несколько вопросов по записи файлов. Использую TFileStream, и уже сильно не уверен, что правильно делаю.
1. Как записать unicodestring в файл, избежав перекодирования в Ansii? Write заполняет файл чем-то похожим на двоичный код, WriteAnsiString записывает текст, но в кодировке Ansii, что логично. Перерыл поисковик, но он упорно подсовывает статьи о том, как удобно перекодировать переменные в Лазарусе (ага, а куда их потом девать?).
2. Как, вообще создать файл указанной кодировки? Умеет ли это TFileStream?
3. Как отучит TFileStream предварять спецсимволы (как он считает) обратными слешами (И нужен ли этот хронически проблемный класс вообще?)?
4. Есть ли встроенная утилита для приведения путей к файлам к UNIX-стандарту?
Последний раз редактировалось Risto 10.03.2016 15:45:25, всего редактировалось 2 раз(а).
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38

Re: Запись файлов юникодом и не только

Сообщение Deimos » 10.03.2016 12:01:49

Risto писал(а):Есть ли встроенная утилита для приведения путей к файлам к UNIX-стандарту?


setdirseparators ??

http://www.freepascal.org/docs-html/rtl/sysutils/setdirseparators.html
Deimos
постоялец
 
Сообщения: 169
Зарегистрирован: 17.01.2010 00:31:30

Re: Запись файлов юникодом и не только

Сообщение Risto » 10.03.2016 12:23:35

Deimos писал(а):setdirseparators


Увы, нет. Она приводит к стандарту системы, то есть тому, от чего я пытаюсь избавиться в Винде.
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38

Re: Запись файлов юникодом и не только

Сообщение wavebvg » 10.03.2016 12:39:07

Статья http://www.freepascal.ru/article/freepa ... 0718142000

Всё зависит от вашей системной локали. Если локаль - не UTF-8, тогда придется немного напрячься, к примеру вот такой способ (из статьи):

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

uses
  Classes,
  SysUtils;

var
  Stream: TFileStream;
  Raw: RawByteString;
begin
  Stream := TFileStream.Create('world.txt', fmCreate);
  try
    Raw := 'Привет мир!';
    SetCodePage(Raw, CP_UTF8, True);
    SetCodePage(Raw, CP_NONE, False);
    Stream.WriteBuffer(Raw[1], Length(Raw));
  finally
    Stream.Free;
  end;
end.


Вообще, реализация довольно замудренная. Можете посмотреть заголовки в compproc.inc и соответствующую реализацию (ALT+CTRL+DOWN в Lazarus), из которых становится понятно, что если Вы не разыменуете UnicodeString, то компилятор сам за Вас сделает "правильную кодировку". Результат получится "правильным", но не таким, каким Вы ожидаете.

Добавлено спустя 4 минуты 35 секунд:
Разделителями занимается вот эта функция:
Код: Выделить всё
Procedure DoDirSeparators (Var FileName : PathStr);
VAr I : longint;
begin
  For I:=1 to Length(FileName) do
    If CharInSet(FileName[I],AllowDirectorySeparators) then
      FileName[i]:=DirectorySeparator;
end;   

Можете её поправить так, как Вам это нужно и использовать. Исходники в fina.inc.
wavebvg
постоялец
 
Сообщения: 354
Зарегистрирован: 28.02.2008 04:57:35

Re: Запись файлов юникодом и не только

Сообщение Risto » 10.03.2016 13:16:23

wavebvg писал(а):
Код: Выделить всё
program RawB;

uses
  Classes,
  SysUtils;

var
  Stream: TFileStream;
  Raw: RawByteString;
begin
  Stream := TFileStream.Create('world.txt', fmCreate);
  try
    Raw := 'Привет мир!';
    SetCodePage(Raw, CP_UTF8, True);
    SetCodePage(Raw, CP_NONE, False);
    Stream.WriteBuffer(Raw[1], Length(Raw));
  finally
    Stream.Free;
  end;
end.



Да, спасибо, так пишется вменяемым текстом, а режим fmCreate вообще стал для меня откровением - в описании класса его не было. Осталось победить проблему с принудительным экранированием:

Код: Выделить всё
{
  "GamePath" : "C:\/Users\/Risto\/Documents\/Homer\/",
  "UserPath" : "C:\/Users\/Risto\/AppData\/Roaming"
}


И вот так эта сволочь портит мне все пути, при записи в файл. Кто подскажет, что делать?
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38

Re: Запись файлов юникодом и не только

Сообщение wavebvg » 10.03.2016 14:11:21

Это генератор JSON-а может (если захочет) экранировать такие символы. Сохранение тут непричем. Читайте/пишите так, чтобы экранирование учитывалось.
wavebvg
постоялец
 
Сообщения: 354
Зарегистрирован: 28.02.2008 04:57:35

Re: Запись файлов юникодом и не только

Сообщение Risto » 10.03.2016 15:44:47

wavebvg писал(а):Это генератор JSON-а может (если захочет) экранировать такие символы. Сохранение тут непричем. Читайте/пишите так, чтобы экранирование учитывалось.

Да, это TJSONObject.AsJSON фигнёй страдал. Спасибо за подсказку.

Добавлено спустя 14 часов 2 минуты 51 секунду:
Re: [Решено] Запись файлов юникодом и не только
Маленькое уточнение: Если написать так:

Код: Выделить всё
SetCodePage(Raw, CP_UTF8, True);
SetCodePage(Raw, CP_NONE, False);


То кодовую страницу переменной вы зададите, а файла, внезапно, - нет, приходится ручками задавать, в текстовом редакторе. Поменять эти строки местами и всё работает.
Risto
незнакомец
 
Сообщения: 9
Зарегистрирован: 10.03.2016 04:11:38


Вернуться в Lazarus

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

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

Рейтинг@Mail.ru