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


Автор: Alex 24.11.2002, 23:46
Привет всем.
У меня вопрос относительно записи массива в файл.
Допустим, у меня массив:

myarray: array [0..99] of integer

Как правильно его записать в файл?
Я делаю так:

mystream:=TFileStream.Create(myfile, fmCreate); //создаю файл
mystream.WriteBuffer(myarray,100); //запись массива в файл
mystream.free; //освобождение потока  

Вроде бы все работает.
Но я потом не могу его прочитать.
Читаю так:

mystream:=tfilestream.Create(myfile,fmOpenRead);
mystream.ReadBuffer(myarray,100);
mystream.free;

Выдает сообщение, что программа выполнила недопустимое действие и будет закрыта.
В чем проблема.

Автор: Vit 25.11.2002, 00:27
Если только это то можно использовать:

Type Tmyarray= array [0..99] of integer;
Var myarray:Tmyarray;
   F:file of Tmyarray;
...
запись:
assignFile(f, 'myfile');
rewrite(f);
write(f,myarray)
closefile(f)

чтение:
assignFile(f, 'myfile');
reset(f);
read(f,myarray)
closefile(f)

Автор: Alex 25.11.2002, 03:42
Вообще-то я там записал сокращенный вариант записи файла.
На самом деле в начало я записываю заголовок типа

header: record of
  name: string[32];
  version: integer;
  sizex: integer;
  sizey: integer;
  end;

Все это делаю через поток (как в первом примере), а потом после заголовка уже записываю сам массив, так что я думаю что твой пример не пойдет.

Автор: Vit 25.11.2002, 03:52
Тогда приводи свой код и полную структуру файла, так как ошибка скорее всего не в том куске который ты привёл, а в том что ты должен читать инфу после header и видимо позиционируешь чтение не с того места, или ещё что-то... Дай более полную инфу и я подумаю, как это сделать

Автор: Alex 29.11.2002, 00:40
Делаю так:
Код для записи в файл
//-------------------
procedure TForm1.ConvertBtnClick(Sender: TObject);
var
Header: record              //заголовок файла-карты
   Name: string[16];      //имя файла
   version: integer;      //номер версии
   SizeX: integer;        //размер карты по Ох
   SizeY: integer;        //размер карты по Оу
   HeightKoef: single;    //коэффициент
 end;
koef: single;
headersize: integer; //размер заголовка
x1,y1,x,y: integer;
heightmap: array of array of byte;  //динамический двумерный массив
arraysize: integer; //размер массива
outstream: tstream; //поток для записи конечного файла
outputfile: string; //выходящий файл
begin
...
setlength(heightmap,x,y); //устанавливаю размер массива
arraysize:=x*y; //размер массива в байтах (приходится вычислять так, т.к. sizeof(heightmap) не работает (всегда возвращает 4)???)
for x1:=0 to x-1 do
   for y1:=0 to y-1 do
       begin
       ...
       heightmap[x1,y1]:=... //здесь заполняю массив
       end;
Header.Name:='HeightMap';   //запись заголовка
header.version:=1;          //запись заголовка
header.SizeX:=x;            //запись заголовка
header.Sizey:=y;            //запись заголовка
header.heightkoef:=koef;    //запись заголовка
headersize:=sizeof(header); //возвращает размер заголовка
OutStream:=TFileStream.Create(OutputFile, fmCreate);//создает поток для записи конечного файла
outstream.WriteBuffer(header,headersize); //запись заголовка в файл
outstream.WriteBuffer(heightmap,arraysize);//запись массива в файл
OutStream.Free; //освобождение потока
end;
//-------------------
Код для чтения из файла
//-------------------
procedure TForm1.LoadSourceMenuClick(Sender: TObject);
var
mapfile: tstream; //поток для чтения файла
myfile: string; //имя файла
Header: record              //заголовок файла-карты
   Name: string[16];      //имя файла
   version: integer;      //номер версии
   SizeX: integer;        //размер карты по Ох
   SizeY: integer;        //размер карты по Оу
   HeightKoef: single;    //коэффициент для расчета высот
 end;
headersize: integer; //размер заголовка
heightmap: array of array of byte;  //двумерный динамический массив
arraysize: integer; //размер массива карты высот
x,y: integer;
begin
...
mapfile:=tfilestream.Create(myfile,fmOpenRead);//создаем поток для чтения файла
headersize:=sizeof(header);
mapfile.ReadBuffer(header,headersize); //читаем заголовок
x:=header.SizeX;
y:=header.SizeY;
setlength(heightmap,x,y); //устанавливаем размер массива
arraysize:=x*y; //вычисляем размер массива в байтах
mapfile.ReadBuffer(heightmap,arraysize); //считываем массив
mapfile.free;
end;
//-------------------
Обе эти процедуры работают. Файл записывается нормально (количество записанных байт соответствует требуемому значению (sizeof(header)+x*y - в моем случае)).
Считывается заголовок тоже нормально.
Проблема в самом массиве, когда я пытаюсь достать из него какое-либо значение, например heightmap[0,0] - ЗДЕСЬ ОШИБКА.

Автор: Alex 6.12.2002, 02:58
Привет, Vit. Мой вопрос еще не закрыт.
Жду ответа...

Автор: Vit 6.12.2002, 04:56
Сорри, забыл...

Так посмотрел твой код

1) Мусор он у тебя в файл пишет, а не массив, так как реально он туда пихает указатель а не содержимое. Кстати поэтому у тебя и размер не работал - естественно - он размер указателя тебе возвращает. Исправь на:

Код

 outstream.Write(Pointer(heightmap)^,arraysize);


Чтение сделай точно так же:

Код

mapfile.Read(Pointer(heightmap)^,arraysize);


2) У меня всё равно неправильно читает, и заглянув внутрь файла я увидел посреди данных мусор, такое впечатление что двумерный массив не хранится в памяти единым блоком (или хрен его знает почему так). Если заменить на одномерный массив то всё нормально. Вывод - хочешь ковыряйся дальше, нет - пиши одномерным массивом - одним большого размера, или просто пиши/читай в цикле одномерные массивы.


Для отладки таких вещей удобно сделать например следующее - берёшь массив 20х20 заполняешь например $40 - пишешь в файл, затем открываешь файл в просмотрщике и смотришь что у тебя записано


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