Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > чтение/сохранения TList


Автор: JS2 25.4.2009, 15:07
имеется наследник TList - TListA список записей типа:

Код

PItemA = ^TItemA;
TItemA = record
 Id: Integer;
 Name: string;
end;


Вручную написал методы сохранения/чтения списка в файл. Вот код:


Код

procedure TListA.LoadFromFile(const FileName: string);
var
 i, L: Integer;
 P: PItemA;
 S: TStream;
begin
 S := TFileStream.Create(FileName, fmOpenRead);
 with S do
   try
     while Position < Pred(Size) do
     begin
       New(P);
       with P^ do
       begin
         Read(Id, SizeOf(Id));
         Read(L, SizeOf(L));
         Read(Name, L);
         Add(Id, Name);
       end;
     end;
   finally
     Free;
   end;
end;

procedure TListA.SaveToFile(const FileName: string);
var
 i, L: Integer;
 P: PItemA;
 S: TStream;
begin
 S := TFileStream.Create(FileName, fmCreate);
 with S do
   try
     for i := 0 to Pred(Count) do
     begin
       P := PItemA(List[i]);
       with P^ do
       begin
         Write(Id, SizeOf(Id));
         L := Length(Name);
         Write(L, SizeOf(L));
         Write(Name, L);
       end;
     end;
   finally
     Free;
   end;
end;



Список вроде как и сохраняется и загружается, но вот только при выводе тестового поля какой-либо записи (ShowMessage(Lst.Items[0].Name)) списка дописываюся лишние символы. В чем может быть ошибка?

Автор: Лапоть 25.4.2009, 18:32
Строки в структурах хороши, пока не надо писать/читать в/из файл(а). Поменяй тип данных для TItemA.Name - на символьный массив заданной длины (что-нибудь типа array [0..127] of char).
Кстати, в этом случае ты сможешь читать/писать запись целиком (она всегда будет одной и той же длины), а не почленно.

Автор: kami 25.4.2009, 18:45
Неправильная работа со строками, а именно - в методах Read и Write.
1. Чтение и запись строк производить нужно, начиная с первого символа, т.е. не str а str[1].
2. При New(p) инициируется пустая строка. Как вы пишете в нее, не установив длину - непонятно (хоть длину строки сохраняете, уже очень хорошо).
Правильно так:
в LoadFromFile вместо Read(Name, L);
Код

SetLength(name, l);
if l<>0 then
  Read(name[1], l);


В SaveToFile вместо Write(Name, L);
Код

if l<>0 then
  Write(Name[1], l);


Добавлено через 3 минуты и 2 секунды
И будет вам счастье невыразимое в работе со строками.  smile 

Цитата(Лапоть @  25.4.2009,  18:32 Найти цитируемый пост)
Строки в структурах хороши, пока не надо писать/читать в/из файл(а)

Они также хороши и при записи/чтении в/из файла. Просто нужно уметь их готовить.

Добавлено через 10 минут и 34 секунды
JS2, еще одно замечание/предложение: не используйте With без крайней необходимости.
причина простая: если бы этот код находился в классе TForm1 (к примеру), то возможно возникновение неявной ошибки:
поле Name есть и у TForm1, и что из них (св-во TForm или поле TItemA) пойдет на чтение/запись - это нужно долго и упорно читать документацию или шагать отладчиком (который, кстати, тоже не очень жалует всплывающими подсказками with).

Автор: Лапоть 25.4.2009, 20:14
Цитата(kami @  25.4.2009,  19:45 Найти цитируемый пост)
Просто нужно уметь их готовить.
 Поздно переучиваться! smile Да и смысла не вижу.
Цитата(kami @  25.4.2009,  19:45 Найти цитируемый пост)
не используйте With без крайней необходимости
 А вот с этим - полностью согласен! smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)