Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.07.05;
Скачать: CL | DM;

Вниз

не верное копирование файла через BlockWrite/BlockRead   Найти похожие ветки 

 
brother ©   (2009-05-15 08:52) [0]

Доброго времени суток!
Суть вот в чем:
Есть файл, из него читаю нужный объем байт и записываю в другой файл, код (черновой):
 assignfile(FromF, "c:\1.txt");
 reset(FromF, 1);

 seek(FromF, header.obj[spinedit1.Value]._seek);

  count:=0;

   AssignFile(ToF, "c:\"+header.obj[spinedit1.Value]._shortname);
   Rewrite(ToF, 1);
   repeat
     BlockRead(FromF, Buf, SizeOf(Buf), NumRead);
     inc(count, NumRead);
     if count>header.obj[spinedit1.Value]._size
     then
       BlockWrite(ToF, Buf, count-header.obj[spinedit1.Value]._size, NumWritten)
     else
       BlockWrite(ToF, Buf, NumRead, NumWritten);
   until (NumRead = 0) or (NumWritten <> NumRead);
   CloseFile(ToF);

Проблемма такая: при окончании копирования, на тестовом файле не дописывается 48 байт.
Отладчиком проверил все переменные:
header.obj[spinedit1.Value]._size = 50200 - корректно
inc(count, NumRead); увеличивает коррекно по 2048
count-header.obj[spinedit1.Value]._size на последнем шаге дает 1000.
не понимаю где я ошибаюсь?


 
Palladin ©   (2009-05-15 08:53) [1]


>  or (NumWritten <> NumRead);

это условие - ошибочно


 
Anatoly Podgoretsky ©   (2009-05-15 09:11) [2]

Наверно здесь

>  seek(FromF, header.obj[spinedit1.Value]._seek);


 
brother ©   (2009-05-15 09:11) [3]

> это условие - ошибочно

все верно, по этому, я в конце копирую не весь буфер а только count-header.obj[spinedit1.Value]._size те 1000 байт и потом это является признаком выхода из цикла


 
brother ©   (2009-05-15 09:12) [4]

> Наверно здесь
>
> >  seek(FromF, header.obj[spinedit1.Value]._seek);

нет, заголовок то файла правильный, я проверил


 
Anatoly Podgoretsky ©   (2009-05-15 09:19) [5]

Может и так, но нам то это неизвестно, особенно структура header.
Кстати и выбор цикла неверный, нужен while
И весь алгоритм вызывает какое то сопротивление, вместо простого и понятного, запутаный.


 
Smile   (2009-05-15 09:21) [6]

> brother ©   (15.05.09 08:52)

Что из себя представляют ToF и FromF?

Textfile, File
или еще что-то?


 
brother ©   (2009-05-15 09:26) [7]

> Что из себя представляют ToF и FromF?

 FromF, ToF: file;


> структура header.


 TObj = record
   _shortname : string[100]; // имя файла без путей
   _size : longword ;  // размер файла
   _seek : longword ;  // смещение относительно начала файла
 end;

 THeader = record
   caption:string[10];
   version:string[3];
   size : longword ; // размер Header
   maxobj : integer; // всего добавлено файлов
   obj : array [1..30] of TObj;
 end;


 
brother ©   (2009-05-15 09:27) [8]

структура исходного файла:
заголовок (header)
файл1
файл2
файл N


 
Smile   (2009-05-15 09:43) [9]

> brother ©

Структура понятна, но все-таки приведи (выложи) сюда 100 - 150 байт файла c:\1.txt


 
brother ©   (2009-05-15 09:48) [10]

> сюда 100 - 150 байт файла c:\1.txt

в первых 3384 байтах этого файла находится Header, и он корректно считывается


 
brother ©   (2009-05-15 09:50) [11]

> c:\1.txt

зы, он НЕ текстовый, это для отладки


 
Smile   (2009-05-15 10:00) [12]

> brother ©   (15.05.09 09:50) [11]

понятно


 
Slym ©   (2009-05-15 10:51) [13]

var
 Source,Dest:TFileStream;
 Header:THeader;
 Objs:array of TObj;
 i:integer;
begin
 Source:=TFileStream.Create("c:\1.txt",fmOpenRead);
 try
   Source.ReadBuffer(Header,SizeOf(Header));
   SetLength(Objs,Header.maxobj);
   for i:=0 to Header.maxobj do
     Source.ReadBuffer(objs[i],SizeOf(TObj));
   with Objs[1{spinedit1.Value}] do
   begin
     if Source.Seek(_seek+_size,soBeginning)<>_seek then raise Exception.Create("bad file");
     if Source.Seek(_seek,soBeginning)<>_seek then raise Exception.Create("bad file");
     Dest:=TFileStream.Create("c:\"+_shortname,fmCreate);
     try
       Dest.CopyFrom(Source,_size);
     finally
       Dest.Free;
     end;
   end;
 finally
   Source.Free;
 end;
end;


 
Slym ©   (2009-05-15 10:52) [14]

упс криво...
type
 TObj = packed record
  _shortname : string[100]; // имя файла без путей
  _size : longword ;  // размер файла
  _seek : longword ;  // смещение относительно начала файла
end;

THeader = packed record
  caption:string[10];
  version:string[3];
  size : longword ; // размер Header
  maxobj : integer; // всего добавлено файлов
end;

procedure TForm1.FormCreate(Sender: TObject);
var
 Source,Dest:TFileStream;
 Header:THeader;
 Objs:array of TObj;
 i:integer;
begin
 Source:=TFileStream.Create("c:\1.txt",fmOpenRead);
 try
   Source.ReadBuffer(Header,SizeOf(Header));
   SetLength(Objs,Header.maxobj);
   for i:=0 to Header.maxobj do
     Source.ReadBuffer(objs[i],SizeOf(TObj));
   with Objs[1{spinedit1.Value}] do
   begin
     if Source.Seek(_seek+_size,soBeginning)<>_seek then raise Exception.Create("bad file");
     if Source.Seek(_seek,soBeginning)<>_seek then raise Exception.Create("bad file");
     Dest:=TFileStream.Create("c:\"+_shortname,fmCreate);
     try
       Dest.CopyFrom(Source,_size);
     finally
       Dest.Free;
     end;
   end;
 finally
   Source.Free;
 end;
end;


 
Slym ©   (2009-05-15 10:58) [15]

или можно так:
   Source.ReadBuffer(Header,SizeOf(Header));
   Offset:=SizeOf(Header)+(Header.maxobj-1)*SizeOf(TObj);
   if Source.Seek(Offset,soBeginning)<> Offset then raise Exception.Create("bad file");
   Source.ReadBuffer(Obj,SizeOf(Obj));
   with Obj do
   begin


 
brother ©   (2009-05-18 06:15) [16]

на [14] остановлюсь, но почему
> Objs:array of TObj;

вынес из
> THeader

? ведь инфу я и записываю и считываю, а этот вариант только для чтения?


 
Slym ©   (2009-05-18 06:58) [17]

brother ©   (18.05.09 6:15) [16]
brother ©   (15.05.09 9:26) [7]
THeader = record
  caption:string[10];
  version:string[3];
  size : longword ; // размер Header
  maxobj : integer; // всего добавлено файлов
  obj : array [1..30] of TObj;
end;

Твой формат явно указывает колво файлов заголовком! размер заголовка даже при одном файле будет включать в себя еще 29 пустышек

Slym ©   (15.05.09 10:52) [14]
THeader = packed record
 caption:string[10];
 version:string[3];
 size : longword ; // размер Header
 maxobj : integer; // всего добавлено файлов
end;

мой заголовок будет работать при колве файлов от нуля до MaxInt
size : longword ; - вообще лишнее так как избыточно и ни на что не влияет при моем подходе

Objs:array of TObj; - это какраз твой obj : array [1..30] of TObj; только в динамической реализации и вынесено из заголовка т.к. поле изменяемой длинны
при доступе к файлу считывается заголовок, анализируется колво файлов и все хедеры файлов вычитываются в массив
можно не читать все хедеры а прыгнуть по индексу и читатьт только нужный хедер файла как в Slym ©   (15.05.09 10:58) [15]
brother ©   (18.05.09 6:15) [16]
? ведь инфу я и записываю и считываю, а этот вариант только для чтения?

написать запись чуть сложнее, но не намного...
основная сложность в дозаписи и перезаписи файла с изменением длинны:
нужно сдвигать фсе остальные данные но это не принципиальная сложность
нужно


 
brother ©   (2009-05-18 07:08) [18]

> Objs:array of TObj; - это какраз твой obj : array [1..30]
> of TObj; только в динамической реализации и вынесено из
> заголовка т.к. поле изменяемой длинны

это я понял, но я не понял откуда возьмутся записи, ведь в THeader этих записей нет значит данных в Objs:array of TObj; также нет...


 
brother ©   (2009-05-18 07:10) [19]

> Твой формат явно указывает колво файлов заголовком! размер
> заголовка даже при одном файле будет включать в себя еще
> 29 пустышек

это то я понял)
и
> THeader = packed record

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


 
Slym ©   (2009-05-18 07:36) [20]

код записи без дозаписи/перезаписи
type
TObj = packed record
 _shortname : string[100]; // имя файла без путей
 _size : longword ;  // размер файла
 _seek : longword ;  // смещение относительно начала файла
end;

THeader = packed record
 caption:string[10];
 version:string[3];
 size : longword ; // размер Header
 maxobj : integer; // всего добавлено файлов
end;

procedure CreateFileExample(const DestFileName:string;const FileNames:array of string);
var
Dest,Source:TFileStream;
Header:THeader;
Objs:array of TObj;
i:integer;
begin
 Header.caption:="Write test";
 Header.version:="1.0";
 Header.maxobj:=Length(FileNames);
 Header.size:=SizeOf(THeader)+SizeOf(TObj)*Header.maxobj;
 SetLength(Objs,Header.maxobj);
 Dest:=TFileStream.Create(DestFileName,fmCreate);
 try
   Dest.Size:=Header.size;
   Dest.Position:=Header.size;
   for i:=0 to Header.maxobj-1 do
   begin
     Source:=TFileStream.Create(FileNames[i],fmOpenRead);
     try
       with Objs[i] do
       begin
         _shortname:=ExtractFileName(FileNames[i]);
         _size:=Source.Size;
         _seek:=Dest.Position;
       end;
       Dest.CopyFrom(Source,0);
     finally
       Source.Free;
     end;
   end;
   Dest.Seek(0,soBeginning);
   Dest.WriteBuffer(Header,SizeOf(Header));
   for i:=0 to Header.maxobj-1 do
     Dest.WriteBuffer(Objs[i],SizeOf(TObj));
 finally
  Dest.Free;
 end;
end;

procedure GetFileExample(const SourceFileName,DestDir:string;const FileIndex:integer);
var
Source,Dest:TFileStream;
Header:THeader;
Obj:TObj;
Offset:integer;
begin
Source:=TFileStream.Create(SourceFileName,fmOpenRead);
try
 Source.ReadBuffer(Header,SizeOf(Header));
  Offset:=SizeOf(Header)+(Header.maxobj-1)*SizeOf(TObj);
  if Source.Seek(Offset,soBeginning)<> Offset then raise Exception.Create("bad file");
  Source.ReadBuffer(Obj,SizeOf(Obj));
  with Obj do
  begin
    if Source.Seek(_seek+_size,soBeginning)<>(_seek+_size) then raise Exception.Create("bad file");
    if Source.Seek(_seek,soBeginning)<>_seek then raise Exception.Create("bad file");
    Dest:=TFileStream.Create(IncludeTrailingPathDelimiter(DestDir)+_shortname,fmCreate);
    try
      Dest.CopyFrom(Source,_size);
    finally
      Dest.Free;
    end;
  end;
finally
  Source.Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 CreateFileExample("C:\1.txt",["C:\11.txt","C:\12.txt","C:\13.txt"]);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 GetFileExample("c:\1.txt","c:\",1);
end;


 
Slym ©   (2009-05-18 07:37) [21]

brother ©   (18.05.09 7:10) [19]
как раз гарантированный размер! игнорируя алигны полей


 
brother ©   (2009-05-18 07:56) [22]

> GetFileExample("c:\1.txt","c:\",1);

ошибка: Cannot create file c:\абракадабра...
 Source.ReadBuffer(Obj,SizeOf(Obj));
читает мусор, я так не понимаю причем тут:
Offset:=SizeOf(Header)+(Header.maxobj-1)*SizeOf(TObj);
где тут получение: _seek+_size итд? ты же вроде как эти данные даж не записывал?


 
brother ©   (2009-05-18 07:58) [23]


THeader = record
  caption:string[10];
  version:string[3];
  size : longword ; // размер Header
  maxobj : integer; // всего добавлено файлов
  obj : array [1..30] of TObj;
end;

я их специально в хедер поместил, чтобы прочитав хедер, знать и размер и смещения и шортимя...


 
Slym ©   (2009-05-18 08:07) [24]

brother ©   (18.05.09 7:58) [23]
так убери... мой пример приведен для убранного...
я тебе объясняю у тебя поле статичной длинны а это неправильно
я сделал динамической длинны
brother ©   (18.05.09 7:56) [22]
Offset:=SizeOf(Header)+(Header.maxobj-1)*SizeOf(TObj);
где тут получение: _seek+_size итд? ты же вроде как эти данные даж не записывал?


Offset:=SizeOf(Header)+(Header.maxobj-1)*SizeOf(TObj);
 if Source.Seek(Offset,soBeginning)<> Offset then raise Exception.Create("bad file");
 Source.ReadBuffer(Obj,SizeOf(Obj));

получение


 
brother ©   (2009-05-18 08:09) [25]

> так убери... мой пример приведен для убранного...

я убрал конечно, ошибка: Cannot create file c:\абракадабра...

> Source.ReadBuffer(Obj,SizeOf(Obj));

прилетает мусор


 
Slym ©   (2009-05-18 08:12) [26]

packed record?


 
Slym ©   (2009-05-18 08:17) [27]

файл записанный моим кодом прекрасно читается моим же способом


 
brother ©   (2009-05-18 08:26) [28]

> файл записанный моим кодом прекрасно читается моим же способом

да все ок...


 
brother ©   (2009-05-18 08:34) [29]

> procedure GetFileExample(const SourceFileName,DestDir:string;
> const FileIndex:integer);

только ты его не используешь, и несмторя на:

> GetFileExample("c:\1.txt","c:\",1);

грузишь последний добавленый файл)


 
Slym ©   (2009-05-18 09:15) [30]

procedure GetFileExample(const SourceFileName,DestDir:string;const FileIndex:integer);
var
Source,Dest:TFileStream;
Header:THeader;
Obj:TObj;
Offset:integer;
begin
 Source:=TFileStream.Create(SourceFileName,fmOpenRead);
 try
  Source.ReadBuffer(Header,SizeOf(Header));
  Offset:=SizeOf(Header)+FileIndex*SizeOf(TObj);
  if Source.Seek(Offset,soBeginning)<> Offset then raise Exception.Create("bad file");
  Source.ReadBuffer(Obj,SizeOf(Obj));
  with Obj do
  begin
    if Source.Seek(_seek+_size,soBeginning)<>(_seek+_size) then raise Exception.Create("bad file");
    if Source.Seek(_seek,soBeginning)<>_seek then raise Exception.Create("bad file");
    Dest:=TFileStream.Create(IncludeTrailingPathDelimiter(DestDir)+_shortname,fmCreate);
    try
      Dest.CopyFrom(Source,_size);
    finally
      Dest.Free;
    end;
  end;
finally
  Source.Free;
end;
end;


 
brother ©   (2009-05-18 09:27) [31]

да поправил уже спасибо!
зы Offset:=SizeOf(Header)+(FileIndex-1)*SizeOf(TObj2);   ;))))


 
Slym ©   (2009-05-18 09:31) [32]

brother ©   (18.05.09 9:27) [31]
FileIndex-1

Зочем? принято нумеровать от нуля...


 
brother ©   (2009-05-18 09:47) [33]

> Зочем? принято нумеровать от нуля...

чтоб спинедит не корректировать


 
Slym ©   (2009-05-18 09:53) [34]

Slym ©   (18.05.09 9:31) [32]
и кошернее обернуть все это в объектную оболочку
типа
TFileContainer.Create(FileName);
TFileContainer.Count
TFileContainer.AddStream(FileName)
TFileContainer.AddFile(FileName)
TFileContainer.GetFileInfo(index)
TFileContainer.SaveToStream(index,path)
TFileContainer.SaveToFile(index,path)


 
brother ©   (2009-05-18 09:57) [35]

> и кошернее обернуть все это в объектную оболочку

подумаю, о кошерности) спасибо!



Страницы: 1 вся ветка

Текущий архив: 2009.07.05;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.02 c
4-1212234617
hub00
2008-05-31 15:50
2009.07.05
Область подсвечивания.


15-1241555404
Юрий
2009-05-06 00:30
2009.07.05
С днем рождения ! 6 мая 2009 среда


2-1242577574
Wind
2009-05-17 20:26
2009.07.05
Получить список Экспортируемых функций


2-1242548506
Tenebrae
2009-05-17 12:21
2009.07.05
Компонента Comport


15-1240919561
pasha_golub
2009-04-28 15:52
2009.07.05
Плейлист боевого настроения