Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> BlockRead & BlockWrite, вылетает ошибка... 
:(
    Опции темы
artemiy
Дата 29.3.2007, 22:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Использую BlockRead & BlockWrite для записи динамического массива записей в файл.
Вот код:
Код

type
  TOptions = record
    line1,line2:string;
    value:boolean;
  end;

var
  data:array of TOptions;
  f:file;

procedure SaveAll;
var i,x:integer;
begin
 AssignFile(f,'test-save.sav');
 Rewrite(f);
 x:=Length(data);
 BlockWrite(f,x,4);
 for i:=0 to x-1 do
      begin
        x:=SizeOf(data[i]);
        BlockWrite(f,x,4);
        BlockWrite(f,data[i],SizeOf(data[i]));
      end;
 CloseFile(f);
end;

procedure RestoreAll;
var i,x:integer;
begin
 AssignFile(f,'test-save.sav');
 Reset(f);
 BlockRead(f,x,4);
 SetLength(data,x);
 for i:=0 to x-1 do
      begin
        BlockRead(f,x,4);
        BlockRead(f,data[i],x);
      end;
 CloseFile(f);
end;

И у меня вылетает ошибка на выходе из процедуры RestoreAll. Почему - не знаю :( Может кто подскажет где ошибка?
PM MAIL   Вверх
VICTAR
Дата 29.3.2007, 22:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1108
Регистрация: 6.10.2006

Репутация: 10
Всего: 80



А где размер записи? По умолчанию он 128 байт
Код

Rewrite(f,1);


Добавлено через 3 минуты и 50 секунд
Плюс при чтении указывай параметр, в который будет возвращаться кол-во прочитанных записей. Если ты не указываешь этот параметр, а кол-во прочтенных записей будет меньше размера буфера получишь исключение.

Код

var count: integer;
BlockRead(f,x,4,count);

PM MAIL   Вверх
artemiy
Дата 29.3.2007, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Добавил... Теперь у меня следующее:
Код

type
  TOptions = record
    line1,line2:string;
    value:boolean;
  end;
var
  data:array of TOptions;
  f:file;
procedure SaveAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Rewrite(f,1);
 x:=Length(data);
 BlockWrite(f,x,4,count);
 for i:=0 to Length(data)-1 do
      begin
        x:=SizeOf(data[i]);
        BlockWrite(f,x,4,count);
        BlockWrite(f,data[i],SizeOf(data[i]),count);
      end;
 CloseFile(f);
 SetLength(data,0);
end;

procedure RestoreAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Reset(f,1);
 BlockRead(f,x,4,count);
 SetLength(data,x);
 for i:=0 to Length(data)-1 do
      begin
        BlockRead(f,x,4,count);
        BlockRead(f,data[i],x,count);
      end;
 CloseFile(f);
end;

Работает почти без ошибок (на этот раз ошибка при закрытиии программы), но читает неправильно... 
З.Ы. Это мой первый опыт работы с BlockRead & BlockWrite. 

Это сообщение отредактировал(а) artemiy - 29.3.2007, 23:01
PM MAIL   Вверх
VICTAR
Дата 29.3.2007, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1108
Регистрация: 6.10.2006

Репутация: 10
Всего: 80



Можно работать с ShortString, например так
Код

type
  TOptions = record
    line1,line2: ShortString;
    value:boolean;
  end;
var
  data:array of TOptions;
  f:file;

procedure SaveAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Rewrite(f,1);
 x:=Length(data);
 BlockWrite(f,x,4,count);
 for i:=0 to Length(data)-1 do
  BlockWrite(f,data[i],SizeOf(TOptions));
 CloseFile(f);
 SetLength(data,0);
end;

procedure RestoreAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Reset(f,1);
 BlockRead(f,x,4,count);
 SetLength(data,x);
 for i:=0 to Length(data)-1 do
  BlockRead(f,data[i],SizeOf(TOptions),count);
 CloseFile(f);
end;

PM MAIL   Вверх
MetalFan
Дата 30.3.2007, 08:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



опять циклы... зачем? если размер записи заранее известен...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
artemiy
Дата 30.3.2007, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Цитата(VICTAR)
Можно работать с ShortString
 Так а чем этот ShortString помог?

У меня проблема вообще вот в чем: надо записать несколько массивов рекордов в файл. Это динамические массивы разных рекордов, причем размер одинаковых рекордов не всегда совпадает. Решение я вижу таким: записывать в файл сначала размерность первого массива, затем записывать размер каждого элемента массива(размер рекорда) и собственно сам элемент(рекорд). Затем записывать размерность второго массива и его элементы с размерами. И т.д. Считывать я собираюсь так же: считал размерность массива, потом все его элементы...

Записывать вроде бы получается, а вот считывать - нет (считывает фигню какую-то, см. скриншот). Где проблема - я не знаю :(

Присоединённый файл ( Кол-во скачиваний: 5 )
Присоединённый файл  untitled.JPG 26,32 Kb
PM MAIL   Вверх
MetalFan
Дата 30.3.2007, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Цитата(artemiy @  30.3.2007,  10:56 Найти цитируемый пост)
динамические массивы разных рекордов

эт как это на делфи такое сделать можно?!  smile


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
VICTAR
Дата 30.3.2007, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1108
Регистрация: 6.10.2006

Репутация: 10
Всего: 80



Цитата(MetalFan @  30.3.2007,  08:52 Найти цитируемый пост)
опять циклы... зачем? если размер записи заранее известен... 

MetalFan, злой ты человек  smile, это задумка автора(если эта реплика была не ко мне звиняй  smile )

Цитата(artemiy @  30.3.2007,  10:56 Найти цитируемый пост)
Так а чем этот ShortString помог?

Тем, что выравнял "рекорд". Мое дело предложить.


Цитата(artemiy @  30.3.2007,  10:56 Найти цитируемый пост)
Решение я вижу таким: записывать в файл сначала размерность первого массива, затем записывать размер каждого элемента массива(размер рекорда) и собственно сам элемент(рекорд). 

только не забудь тогда записывать еще размер каждого эл-та записи(для строк)  smile 
PM MAIL   Вверх
artemiy
Дата 30.3.2007, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Цитата(MetalFan)

Цитата(artemiy @  30.3.2007,  10:56 Найти цитируемый пост)
динамические массивы разных рекордов

эт как это на делфи такое сделать можно?!  smile
Это в смысле что один массив состоит из одних рекордов, другой массив - из других smile
Цитата(VICTAR)

только не забудь тогда записывать еще размер каждого эл-та записи(для строк)  smile

Ну так я так и делаю ))
Вот код с комментами:
Код

type
  TOptions = record
    line1,line2:string;
    value:boolean;
  end;
var
  data:array of TOptions;
  f:file;

procedure SaveAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Rewrite(f,1);
 x:=Length(data);
 BlockWrite(f,x,4,count);   //Записываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
        x:=SizeOf(data[i]);
        BlockWrite(f,x,4,count);     //Записываем размер записи
        BlockWrite(f,data[i],SizeOf(data[i]),count);    //Записываем саму запись
      end;
 CloseFile(f);
 SetLength(data,0);
end;

procedure RestoreAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Reset(f,1);
 BlockRead(f,x,4,count);
 SetLength(data,x);        //Считываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
        BlockRead(f,x,4,count);    //Считываем размер записи
        BlockRead(f,data[i],x,count);    //Считываем саму запись
      end;
 CloseFile(f);
end;

Но вот только я не пойму почему оно неправильно считывается...  MetalFan, или ты имеешь в виду записывать еще и размерность каждого элемента записи? Т.е. записывать каждый элемент по отдельности, а не всю запись сразу... Если да, то, блин, геморно получается...

Может быть стоит использовать вообще другой алгоритм?

Это сообщение отредактировал(а) artemiy - 30.3.2007, 12:53
PM MAIL   Вверх
MetalFan
Дата 30.3.2007, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



а! ну дык понятно...
код и не будет работать, если использовать длинные строки. да и вообще код написан с грубейщими ошибками.
а записывать размерность каждой записи - это лишнее, они всегда одинаковые будут)



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
artemiy
Дата 30.3.2007, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Цитата(MetalFan)
да и вообще код написан с грубейщими ошибками.

А где именно? Буду исправлять.

Цитата(MetalFan)
а записывать размерность каждой записи - это лишнее, они всегда одинаковые будут)

А если елементами рекорда будут STringList'ы?
PM MAIL   Вверх
MetalFan
Дата 30.3.2007, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Цитата(artemiy @  30.3.2007,  13:25 Найти цитируемый пост)
Цитата(MetalFan)
да и вообще код написан с грубейщими ошибками.

А где именно? Буду исправлять.

беру слова обратно. просто есть некторые недочеты. эт с первого взгляда не так понял)

Цитата(artemiy @  30.3.2007,  13:25 Найти цитируемый пост)

А если елементами рекорда будут STringList'ы? 

и что? 4 байта в записи займет. как и любой другой наследник от TObject


Это сообщение отредактировал(а) MetalFan - 30.3.2007, 14:00


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
artemiy
Дата 30.3.2007, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Цитата(MetalFan @  30.3.2007,  13:35 Найти цитируемый пост)
4 байта в записи займет. как и любой другой наследник от TObject

Даже если в этом TStringList'е будет текста на несколько килобайт?
PM MAIL   Вверх
artemiy
Дата 30.3.2007, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Немного переделал код:
Код

type
  TOptions = record
    line1,line2:string;
    text:TStringList;
    value:boolean;
  end;
var
  data:array of TOptions;
  f:file;

procedure SaveRecord(rec:TOptions);
var size,count:integer;
begin
 with rec do
 begin
   size:=SizeOf(Line1);
   BlockWrite(f,size,4,count);
   BlockWrite(f,Line1,size,count);

   size:=SizeOf(line2);
   BlockWrite(f,size,4,count);
   BlockWrite(f,line2,size,count);

   size:=SizeOf(text);
   BlockWrite(f,size,4,count);
   BlockWrite(f,text,size,count);

   BlockWrite(f,value,1,count);
 end;
end;

procedure ReadRecord(var rec:TOptions);
var size,count:integer;
begin
 with rec do
 begin
   BlockRead(f,size,4,count);
   BlockRead(f,line1,size,count);

   BlockRead(f,size,4,count);
   BlockRead(f,line2,size,count);

   text:=TStringList.Create;
   BlockRead(f,size,4,count);
   BlockRead(f,text,size,count);

   BlockRead(f,value,1,count);
 end;
end;

procedure SaveAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Rewrite(f,1);
 x:=Length(data);
 BlockWrite(f,x,4,count);   //Записываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
         SaveRecord(data[i]);
      end;
 CloseFile(f);
 SetLength(data,0);
end;

procedure RestoreAll;
var i,x,count:integer;
begin
 AssignFile(f,'test-save.sav');
 Reset(f,1);
 BlockRead(f,x,4,count);
 SetLength(data,x);        //Считываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
        ReadRecord(data[i]);
      end;
 CloseFile(f);
end;

И все равно считывается неправильно...  smile  Может быть мне и TStringList построчно записывать? smile 
PM MAIL   Вверх
VICTAR
Дата 30.3.2007, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1108
Регистрация: 6.10.2006

Репутация: 10
Всего: 80



Не знаю, стоит ли игра свеч  smile... Наверное нужно поискать более оптимальный вариант.
Код

type
  TOptions = record
    line1,line2:string;
    text:TStringList;
    value:boolean;
  end;
var
  data:array of TOptions;
  f:file;

procedure SaveRecord(rec:TOptions);
var size,count:integer;
begin
 with rec do
 begin
   size:=length(Line1);
   BlockWrite(f,size,4);
   BlockWrite(f,Line1[1],size);
   size:=length(line2);
   BlockWrite(f,size,4);
   BlockWrite(f,line2[1],size);
   size:=length(text.Text);
   BlockWrite(f,size,4);
   BlockWrite(f,text.Text[1],size);
   BlockWrite(f,value,1,count);
 end;
end;

procedure ReadRecord(var rec:TOptions);
var size,count:integer;
    tmp: string;
begin
 with rec do
 begin
   BlockRead(f,size,4,count);
   SetLength(line1, size);
   BlockRead(f,line1[1],size,count);
   BlockRead(f,size,4,count);
   SetLength(line2, size);
   BlockRead(f,line2[1],size,count);
   text:=TStringList.Create;
   BlockRead(f,size,4,count);
   SetLength(tmp, size);
   BlockRead(f,tmp[1],size,count);
   text.Text:=tmp;
   BlockRead(f,value,1,count);
 end;
end;

procedure SaveAll;
var i,x,count:integer;
begin
 AssignFile(f,'C:\test-save.sav');
 Rewrite(f,1);
 x:=Length(data);
 BlockWrite(f,x,4,count);   //Записываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
         SaveRecord(data[i]);
      end;
 CloseFile(f);
 SetLength(data,0);
end;

procedure RestoreAll;
var i,x,count:integer;
begin
 AssignFile(f,'C:\test-save.sav');
 Reset(f,1);
 BlockRead(f,x,4,count);
 SetLength(data,x);        //Считываем размерность массива
 for i:=0 to Length(data)-1 do
      begin
        ReadRecord(data[i]);
      end;
 CloseFile(f);
end;


PM MAIL   Вверх
artemiy
Дата 31.3.2007, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 121
Регистрация: 22.2.2007

Репутация: нет
Всего: нет



Спасибо!  smile 
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1099 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.