Собственно, имеется несколько вопросов по записи файлов. Использую TFileStream, и уже сильно не уверен, что правильно делаю.
1. Как записать unicodestring в файл, избежав перекодирования в Ansii? Write заполняет файл чем-то похожим на двоичный код, WriteAnsiString записывает текст, но в кодировке Ansii, что логично. Перерыл поисковик, но он упорно подсовывает статьи о том, как удобно перекодировать переменные в Лазарусе (ага, а куда их потом девать?).
2. Как, вообще создать файл указанной кодировки? Умеет ли это TFileStream?
3. Как отучит TFileStream предварять спецсимволы (как он считает) обратными слешами (И нужен ли этот хронически проблемный класс вообще?)?
4. Есть ли встроенная утилита для приведения путей к файлам к UNIX-стандарту?
[Решено] Запись файлов юникодом и не только
Модератор: Модераторы
[Решено] Запись файлов юникодом и не только
Последний раз редактировалось Risto 10.03.2016 14:45:25, всего редактировалось 2 раза.
Risto писал(а):Есть ли встроенная утилита для приведения путей к файлам к UNIX-стандарту?
setdirseparators ??
http://www.freepascal.org/docs-html/rtl/sysutils/setdirseparators.html
Deimos писал(а):setdirseparators
Увы, нет. Она приводит к стандарту системы, то есть тому, от чего я пытаюсь избавиться в Винде.
Статья http://www.freepascal.ru/article/freepa ... 0718142000
Всё зависит от вашей системной локали. Если локаль - не UTF-8, тогда придется немного напрячься, к примеру вот такой способ (из статьи):
Вообще, реализация довольно замудренная. Можете посмотреть заголовки в compproc.inc и соответствующую реализацию (ALT+CTRL+DOWN в Lazarus), из которых становится понятно, что если Вы не разыменуете UnicodeString, то компилятор сам за Вас сделает "правильную кодировку". Результат получится "правильным", но не таким, каким Вы ожидаете.
Добавлено спустя 4 минуты 35 секунд:
Разделителями занимается вот эта функция:
Можете её поправить так, как Вам это нужно и использовать. Исходники в fina.inc.
Всё зависит от вашей системной локали. Если локаль - не 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 писал(а):Код: Выделить всё
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"
}И вот так эта сволочь портит мне все пути, при записи в файл. Кто подскажет, что делать?
Это генератор JSON-а может (если захочет) экранировать такие символы. Сохранение тут непричем. Читайте/пишите так, чтобы экранирование учитывалось.
wavebvg писал(а):Это генератор JSON-а может (если захочет) экранировать такие символы. Сохранение тут непричем. Читайте/пишите так, чтобы экранирование учитывалось.
Да, это TJSONObject.AsJSON фигнёй страдал. Спасибо за подсказку.
Добавлено спустя 14 часов 2 минуты 51 секунду:
Re: [Решено] Запись файлов юникодом и не только
Маленькое уточнение: Если написать так:
Код: Выделить всё
SetCodePage(Raw, CP_UTF8, True);
SetCodePage(Raw, CP_NONE, False);То кодовую страницу переменной вы зададите, а файла, внезапно, - нет, приходится ручками задавать, в текстовом редакторе. Поменять эти строки местами и всё работает.
