Запись и чтение String из нетипизированного файла

Вопросы программирования на Free Pascal, использования компилятора и утилит.

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

Ответить
Аватара пользователя
Ferrum
новенький
Сообщения: 14
Зарегистрирован: 27.08.2009 10:11:53

Запись и чтение String из нетипизированного файла

Сообщение Ferrum »

При работе со строками:
SizeOf(переменная) выдаёт 0
Length(переменная) выдаёт количество символов в строке

Что и как надо указать в третьем параметре BlockRead/BlockWrite, чтобы строку можно было нормально записать и считать из нетипизированного файла?
И почему при записи в файл строки Ansi получаются не нормальные буквы, а иероглифы? В строке только латинские символы.
Аватара пользователя
Light13
постоялец
Сообщения: 127
Зарегистрирован: 17.07.2009 07:50:10
Откуда: Челябинск

Сообщение Light13 »

покажите как пишите

может стоит так
Write(StringVarible[1], Size);
Аватара пользователя
Ferrum
новенький
Сообщения: 14
Зарегистрирован: 27.08.2009 10:11:53

Сообщение Ferrum »

может стоит так
Write(StringVarible[1], Size);

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

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

procedure WriteToMyFile;
var
  f: File;
  b: Byte;
begin
  AssignFile(f, fname);
  Rewrite(f, 1);

  BlockWrite(f, FWidth, SizeOf(FWidth));
  BlockWrite(f, FHeight, SizeOf(FHeight));
  b := Length(FString);
  BlockWrite(f, b, SizeOf(b));
  BlockWrite(f, FString, b);

  CloseFile(f);
end;


тут у меня есть переменные, объявленные вне процедуры

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

FWidth, FHeight: Single;
FString: String;


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

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

b := SizeOf(FSring);

но эта функция выдаёт 0 при работе с типом String и 4 при работе с AnsiString вне зависимости от реальной длины строки
В коде я специально записываю в файл переменную b, в которой хранится вычесленный размер строковой переменной, чтобы при чтении определить размер строки и правильно её считать. Но каким образом можно получить верный пазмер строки в байтах?
Последний раз редактировалось Ferrum 07.07.2010 16:20:34, всего редактировалось 1 раз.
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

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

L := Length(S);
BlockWrite(F, L, SizeOf(L));
BlockWrite(F, S[1], L * SizeOf(S[1]));

BlockRead(F, L, SizeOf(L));
SetLength(S, L);
BlockRead(F, S[1], L * SizeOf(S[1]));
Аватара пользователя
Ferrum
новенький
Сообщения: 14
Зарегистрирован: 27.08.2009 10:11:53

Сообщение Ferrum »

а почему S[1]? так ведь запишется только первый символ строки
Mr.Smart
долгожитель
Сообщения: 1796
Зарегистрирован: 29.03.2008 00:01:11
Откуда: из леса!

Сообщение Mr.Smart »

бррр

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

BlockWrite(f, FWidth[1], Length(FWidth));

В данном случае тип AnsiString является указателем на цепочку символов
Putnick
новенький
Сообщения: 62
Зарегистрирован: 18.03.2009 12:02:56

Сообщение Putnick »

Ferrum писал(а):а почему S[1]? так ведь запишется только первый символ строки

Нет, так запишутся все символы (а вернее, указанное количество) начиная с первого. В противном случае Вы запишите указатель на свою строку. Как вариант, можно использовать так сказать "классические паскалевские" строки типа shortstring.
Тогда можно так:

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

BlockWrite(f,s,length(s)+1);
в получившейся записи первый (нулевой) байт — длина строки, последующие — собственно текст.
Timid
постоялец
Сообщения: 290
Зарегистрирован: 21.11.2007 20:33:15

Сообщение Timid »

shortstring = array [1..255] of AnsiChar;

Файл в такое не запишешь :)
Vadim
долгожитель
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Сообщение Vadim »

Ferrum
А Вы используйте тип ShortString с предопределённым количеством символов:

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

Type
  TMyString: ShortString[20];

Если все буквы английские, то каждый символ занимает ровно 1 байт. Тут и получается, что размер заранее известен - делайте с ним что хотите.
Аватара пользователя
Ferrum
новенький
Сообщения: 14
Зарегистрирован: 27.08.2009 10:11:53

Сообщение Ferrum »

Vadim, предопределять кол-во символов не имею права: строка заполняется в процессе работы программы и её размер заранее неизвестен.
Putnick, спасибо за совет. Я думал, что работа с AnsiString не отличается от работы с классическими строками. Я так понимаю
{$H+} включает режим, когда тип String = AnsiString, {$H-} - String = ShortString.
Ранее ни c AnsiString, ни с ShortString дел не имел, писал просто String.
Я эммигрант с TP7 :mrgreen: Учился по учебнику Фаронова, там про такое не сказано.
А PChar и AnsiString это одно и то же?
Putnick
новенький
Сообщения: 62
Зарегистрирован: 18.03.2009 12:02:56

Сообщение Putnick »

Ferrum писал(а):А PChar и AnsiString это одно и то же?

Не совсем :wink:
Если коротко, то AnsiString, более сложно реализован, имеет счётчик ссылок, хранит длину строки. PChar — просто указатель на последовательность символов, завершающуюся символом с кодом #0.
Более подробно:http://easyprog.ru/index.php?option=com_content&task=view&id=218&Itemid=35
Аватара пользователя
Дож
энтузиаст
Сообщения: 900
Зарегистрирован: 12.10.2008 16:14:47

Сообщение Дож »

а почему S[1]?

В памяти символы начинаются с S[1] и идут последовательно.
так ведь запишется только первый символ строки

Для верности, конечно, можно навесить что-то в стиле (@(S[1]))^. Но и так должно работать.
Ответить