Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

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


Страницы:   1 2

brother ©   (2009-05-15 08:52:00) 

Доброго времени суток!
Суть вот в чем:
Есть файл, из него читаю нужный объем байт и записываю в другой файл, код (черновой):
 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.
не понимаю где я ошибаюсь?


brother   (2009-05-18 09:57:00) [1]

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

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


Slym   (2009-05-18 09:53:00) [2]

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:47:00) [3]

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

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


Slym   (2009-05-18 09:31:00) [4]

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

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


brother   (2009-05-18 09:27:00) [5]

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


Slym   (2009-05-18 09:15:00) [6]

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 08:34:00) [7]

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

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

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

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


brother   (2009-05-18 08:26:00) [8]

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

да все ок...


Slym   (2009-05-18 08:17:00) [9]

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


Slym   (2009-05-18 08:12:00) [10]

packed record?


brother   (2009-05-18 08:09:00) [11]

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

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

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

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


Slym   (2009-05-18 08:07:00) [12]

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 07:58:00) [13]


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

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


brother   (2009-05-18 07:56:00) [14]

> 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 итд? ты же вроде как эти данные даж не записывал?


Slym   (2009-05-18 07:37:00) [15]

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


Slym   (2009-05-18 07:36:00) [16]

код записи без дозаписи/перезаписи
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;


brother   (2009-05-18 07:10:00) [17]

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

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

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


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

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

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


Slym   (2009-05-18 06:58:00) [19]

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 06:15:00) [20]

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

вынес из
> THeader

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо