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


Автор: Я 25.11.2004, 09:39
Есть структура
Код

type
 FileData = array of record
   Number: integer;    
   FullPath: string;  
   NumOfPlay: integer;
   Rep: integer;      
 end;

В процессе соответсвенно структура заполняется и надо бы её сохранить в файл.
Делаю так:
Код

procedure TForm1.Button2Click(Sender: TObject);
var
 f: file;
begin
 assignfile(f,'c:\file.txt');
 rewrite(f);
 BlockWrite(F, GenFileData, SizeOf(GenFileData));
end;

Фаил создается, его размер 16384б и не зависимо от количество записей не меняется.
Соответсвенно при чтении из него структура остается обсалютно пустой.
Плиз хелп.

Автор: Akella 25.11.2004, 09:52
а ты не пробовал использовать reset

Автор: Я 25.11.2004, 10:07
Пробывал - эффект тот же.

Автор: Satana 25.11.2004, 10:23
А ты не пробовал использовать типизированный файл? или чем он тебя не устраивает?
должно быть чтото типа такого:
Код

type
FileData = array of record
  Number: integer;    
  FullPath: string;  
  NumOfPlay: integer;
  Rep: integer;      
end;



...



procedure TForm1.Button2Click(Sender: TObject);
var
f: file of filedata;
data: FileData
begin
assignfile(f,'c:\file.txt');
rewrite(f);
//заполняешь структуру
Write(F, n);
end;



Автор: я 25.11.2004, 10:35
Satana
Для типизированного файла:
должно быть FullPath: string[255];
Мне это не подходит потому как переменная может выходить за 256 символов (((

Автор: SlaUr 25.11.2004, 10:36
По моему можно обьявить st1:array [1..1000] of char (если я не ошибаюсь)

Автор: Pakshin A. S. 25.11.2004, 11:45
можно исхитриться... ставить разделители в файле, например посалить какой-нить ASCII код... получим следующее:
Number#FullPath#NumOfPlay#Rep#
Только читаться немного дольше будет... smile

Читаем до первого... до второго... до третьего.. до четвертого... получили всё необходимое, если надо повторили... конец по EOF

Автор: Guest 25.11.2004, 12:18
Pakshin A. S.
Да, я тоже к такому выводу пришел, но не хотелось бы так извращаться smile

Автор: Snowy 25.11.2004, 13:16
Ну во-первых нужно давать ReWrite(fn,1) или использовать file of byte.
А во-вторых, если строка неограниченной длинны, то в файл будет кидаться по максимуму. Так что придется кидать все элементы по одному, а перед строкой дополнительно давать размер строки. Просто так рекорд с неограниченной строкой не закинуть.
Код

type
 FileData = record
   Number: integer;    
   NumOfPlay: integer;
   Rep: integer;      
   FullPath: string;  // строку пихаем в конец, т.к. размер плавает
 end;
// ------
procedure Save(fd:FileData); // сохранить элемент типа FileData
var
 f: file of byte;
 i: integer;
begin
 assignfile(f,'c:\file.txt');
 rewrite(f);
 BlockWrite(F, fd, SizeOf(integer)*3); // сохраняем первые 3 интегера
 i:=Length(fd.FullPath); // берем длину стринга
 BlockWrite(F, i, SizeOf(integer)); // пихаем в файл
 BlockWrite(F, fd.FullPath, i); // пихаем данные стринга (ругнется, если ='' - поставь проверку
 CloseFile;
end;

procedure Read(var fd:FileData); // читаем 1 элемент типа FileData
var
 f: file of byte;
 i: integer;
begin
 assignfile(f,'c:\file.txt');
 reset(f);
 BlockRead(F, fd, SizeOf(integer)*3); // читаем первые 3 интегера
 BlockRead(F, i, SizeOf(integer)); // читаем длину строки
 SetLength(fd.FullPath, i); //создаем строку нужной длины
 BlockRead(F, fd.FullPath, i); // читаем в нее данные из файла
 CloseFile;
end;



Вот что-то вроде этого. Я не тестил, возможно сразу не сработает, но отладить можно.
А напрямую писать структуру бесполезно - типизированный файл должен иметь одинаковый размер всех элементов, а он не ограничен...
Для сохранения массива нужно вынести открытие и закрытие наружу и вызывать Save или Read в цикле.

Автор: Alex 25.11.2004, 15:16
Satana, убедительная просьба не давать приблизительных примеров кода, которые человек ни когда не сможет скомпилировать. Вам уже отвечали один раз, что ваш пример не корректный.

Автор: Satana 25.11.2004, 15:22
Alex Хорошо больше не буду...

Автор: Medved 27.11.2004, 04:35

 ! 
 
Вы хоть пробывали скомпилить то, что приводите Satana,Snowy? Если уж помогаете, то делайте это добросовестно. Ни один из приведенных кодов не скомпилиться. Это видно даже на вскидку. Хотел поставить минусы, но передумал. Это последнее предупреждение.

Автор: z-END 27.11.2004, 13:30
Дабы многоувожаемый Pegas никому не поставил по минусу, выкладываю свой вариант решения:
1. немного видоизменим описание типа:
Код

type
TFileData = record
  Number: integer;
  FullPath: string[255]; // если надо больше то можно использовать конструкцию  Array[0..xxxx] of Char;
  NumOfPlay: integer;
  Rep: integer;
end;

Var TheFileData: array of TFileData;

2. Для сохранения:
Код

procedure TForm1.Save(Sender: TObject);
var
f: file;
Count,fLen: Integer;
begin
assignfile(F,'c:\file.txt');
rewrite(F,1);
fLen:=Length(TheFileData);
BlockWrite(F,fLen, SizeOf(Integer));
for Count:=0 to fLen-1 do
 BlockWrite(F, TheFileData[Count], SizeOf(TFileData));
CloseFile(F);
end;

3. Для чтения:
Код

procedure TForm1.Load(Sender: TObject);
var
f: file;
Count, fLen: Integer;
begin
assignfile(F,'c:\file.txt');
Reset(F,1);
BlockRead(F,fLen,SizeOf(Integer));
SetLength(TheFileData,fLen);
for Count:=0 to fLen-1 do
 BlockRead(F, TheFileData[Count], SizeOf(TFileData));
CloseFile(F);
end;

ЗЫ надеюсь мой код рабочийsmile

Автор: Snowy 29.11.2004, 09:07
1. Можно помочь просто примером кода. Пример структуры, пример конструкции, пример использования функции и т.п.
2. Не у всех есть время, чтобы полностью все проверить и отладить. Времени жалко но разве это повод не помочь человеку?
3. Человек не защищен он опечаток и мелких ошибок. Я свой код набивал прямо в браузере, поэтому нет ничего ужасного в том, что я забыл поставить (f) после CloseFile.

Теперь по теме. В моем коде нужно добавить (f) после обеих CloseFile и добавить [1] после fd.FullPath. Теперь уж проверил. Точно работает. Можете взять старый код, исправить эти недочеты и все заработает.

Пойдем далее. Так уж и быть, потратил время, сделал РАБОЧИЙ код по циклы.
Код

program Project;
{$APPTYPE CONSOLE}
uses
 SysUtils;

type
 FileData = record
   Number: integer;
   NumOfPlay: integer;
   Rep: integer;
   FullPath: string;  // строку пихаем в конец, т.к. размер плавает
 end;

var
 f: file of byte;
 a,b: array[1..20] of FileData;
 i: integer;
// ------
procedure Save(fd:FileData); // сохранить элемент типа FileData
var
 i: integer;
begin
 BlockWrite(f, fd, SizeOf(integer)*3); // сохраняем первые 3 интегера
 i:=Length(fd.FullPath); // берем длину стринга
 BlockWrite(f, i, SizeOf(integer)); // пихаем в файл
 if i>0 then BlockWrite(f, fd.FullPath[1], i); // пихаем данные стринга
end;

procedure Read(var fd:FileData); // читаем 1 элемент типа FileData
var
 i: integer;
begin
 BlockRead(f, fd, SizeOf(integer)*3); // читаем первые 3 интегера
 BlockRead(f, i, SizeOf(integer)); // читаем длину строки
 if i>0 then begin
   SetLength(fd.FullPath, i); //создаем строку нужной длины
   BlockRead(f, fd.FullPath[1], i); // читаем в нее данные из файла
 end else fd.FullPath:=''; // пустых строк нет в файле!
end;

 // Начинаем тест работоспособности кода:
begin
 for i:=1 to 40 do
 begin
   a[i].Number:=20+i;
   a[i].NumOfPlay:=30+i;
   a[i].Rep:=40+i;
   a[i].FullPath:='Hello '+IntToStr(i)+'`st World!';
 end;

 assignfile(f,'c:\file.txt');
 rewrite(f);
 for i:=1 to 40 do Save(a[i]);
 CloseFile(f);
 //---
 Reset(f);
 for i:=1 to 40 do Read(b[i]);
 CloseFile(f);

 for i:=1 to 40 do
 begin
   WriteLn(b[i].Number);
   WriteLn(b[i].NumOfPlay);
   WriteLn(b[i].Rep);
   WriteLn(b[i].FullPath);
 end;
end.


Код работает, проверен. Можно переделывать под свои нужды. Размер файла с данными гораздо меньше, чем при использовании фиксированного рекорда.

Автор: p0s0l 29.11.2004, 14:04
Цитата(Pegas @ 27.11.2004, 04:35)
Вы хоть пробывали скомпилить то, что приводите Satana,Snowy? Если уж помогаете, то делайте это добросовестно. Ни один из приведенных кодов не скомпилиться. Это видно даже на вскидку. Хотел поставить минусы, но передумал. Это последнее предупреждение.
Зря ты так, Pegas... smile
Это жестоко - ставить минус человеку за попытку помочь...
Так можно отбить у людей всё желание помогать...

Согласен с Snowy, я тоже иногда пишу код прямо в браузере, не проверяя на работоспособность/компилируемость... Особенно, когда нужно показать не рабочий код, а только идею, наброски реализации...

Автор: Medved 29.11.2004, 16:23
Я думаю незря p0s0l, надо с ответственностью относиться к своей помощи. Надо стремиться, чтобы это был форум профессионалов, а не мусорка кода. ИМХО это не жестоко, а правильно. Зря Посол ты это здесь обсуждешь, а не в специальном разделе. Вот это действительно зря.

Автор: Fantasist 30.11.2004, 02:26
Как более удобный, наглядный и абстрагированный вариант:

http://forum.sources.ru/index.php?showtopic=39802&unread=&st=15&#entry260625
http://forum.sources.ru/index.php?showtopic=40114

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