Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2009.07.05;
Скачать: [xml.tar.bz2];

Вниз

не верное копирование файла через 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.005 c
8-1194476253
Проходящий мимо
2007-11-08 01:57
2009.07.05
Flash


3-1223294960
DelphiN!
2008-10-06 16:09
2009.07.05
Утечка памяти при работе с TIbDataSet


2-1242370566
luiziann
2009-05-15 10:56
2009.07.05
Операторы цикла


3-1223445286
edk2
2008-10-08 09:54
2009.07.05
помогите!!!!!


8-1194953765
Lebedev
2007-11-13 14:36
2009.07.05
Проблема с MediaPlayer.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский