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

Вниз

Алгоритм деления файла на фрагменты.   Найти похожие ветки 

 
Фёдор Мегатронов   (2005-01-10 02:42) [0]

Вобщем мне надо один файл поделить на заданное колличество кусков и затем их записать в один.
Если с сборкой кусков в исходный файл никаких проблем, то вот с ПРАВИЛЬНЫМ делением исходного файла- одни проблемы.

Мой алгоритм
{размер всех кусков кроме последнего}
размер куска := размер файла div на кол-во кусков

затем я считываю из файла по байту в буффер и записываю их в другой файл до тех пор пока он не станет равер размеру куска.

далее указатель устанавливаеться на исходный файл на размер куска + 1 и опять считывается в буффер до тех пор пока он не будет равен куску файла и затем записываеться в новый файл - второй кусок.

Вобщем штука такая, что почему-то в куски записываеться не то колличество байт которое нужно. И сложно сказать правильный ли размер имеет первый кусок и последний.

Не могли бы вы подсказать какой-нибудь алгоритм разбиения файла на куски с дальшейшим их соединением обратно в рабочий файл ?


 
jack128 ©   (2005-01-10 02:55) [1]

Давай, показывай, что ты наваял :-) Нахаляву готовый код получить не удасться ;-)


 
Фёдор Мегатронов   (2005-01-10 03:07) [2]

Вот куски кода отвечающие за деление файла (файл делиться условно, т.к. он в инете)


FPartSize := FSizeBytes div Form2.Parts;

{этот ИФ нужен для того чтобы выполнилось условие в цикле REPEAT}
If (FPartSize mod irfBytesToRead ) <> 0
 then
  begin

   Repeat
    Inc(irfBytesToRead);
   Until (FPartSize mod irfBytesToRead) = 0

  end;

{ Открываем файл на винче }
if FileExists(Form2.FileDir + IntToStr(Form2.Part) + "_partof_" + Form2.FileName)
 then
  begin
   AssignFile(F, Form2.FileDir + IntToStr(Form2.Part) + "_partof_" + Form2.FileName);
   Reset(F, 1);
   FPos := FileSize(F);
   Seek(F, FileSize(F));
  end
 else
  try
   AssignFile(F, Form2.FileDir + (IntToStr(Form2.Part) + "_partof_" + Form2.FileName));
   Rewrite(F, 1);
  except
   Application.MessageBox("Недопустимые символы в имени файла!","Ошибка!");
   Exit;
  end;

{ Проверяем файл на возможность докачки }
if FPos > 0
 then
  begin
   InternetSetFilePointer(hURL, FPos, nil, 0, 0);
  end
 else
  begin

   case Form2.Part of

    1:
      begin
       FPos := 0;
      end;

    2:
      begin
       FPos := FPartSize + 1024;
      end;

    3:
      begin
       FPos := FPartSize * 2 + 1024;
      end;

    4:
      begin
       FPos := FPartSize * 3 + 1024;
      end;

    5:
      begin
       FPos := FPartSize * 4 + 1024;
      end;

   end; {of case}

   InternetSetFilePointer(hURL, FPos, nil, 0, 0);
  end;

{ Создаём буфер для считывания }
GetMem(irfBuffer, irfBytesToRead);

{ Запускаем основной цикл скачивания }
REPEAT

 { проверка на завершение потока }
 If Terminated
 then
  begin
   Application.MessageBox("Процесс прерван. Всё что было скачано - сохранено. Чтобы продолжить закачку позже - просто начните скачивать этот-же файл","Процесс прерван");
   InternetCloseHandle(hSession);
   InternetCloseHandle(hUrl);
   CloseFile(F);
   Synchronize(RefreshOnStop);
   Exit;
  end;

 { Проверка на кол-во реально прочитанных байт }
 NoError := InternetReadFile(hURL, irfBuffer, irfBytesToRead, irfBytesReaded);

 { Если они равны нулю, то ничего не качаем}
 if NoError = false
  then
   begin
    Application.MessageBox("Неправельно указан адрес файла, либо он отсутствует на сервере", "Ошибка!");
    InternetCloseHandle(hSession);
    InternetCloseHandle(hUrl);
    CloseFile(F);
    FreeMem(irfBuffer, irfBytesToRead);
    Synchronize(RefreshOnStop);
    Exit;
   end
  else
   begin
    BlockWrite(F, irfBuffer^, irfBytesReaded);

    { Прогресс }
    Synchronize(RefreshGauge);
    Synchronize(RefreshBytesToGo);
   end;

{ Пока будет что читать }
UNTIL ((FileSize(F) = FPartSize) and (Form2.Parts <> Form2.Part)) or (irfBytesReaded = 0);


в конце концов файл на КБ больше исходного.

У меня там было много комбинаций в CASE .. и отнимал там 1024 и прибавлял 1 ... и чего только не далал методом тыка 8) ..
потому что так ка кджолжно почему-то не работает 8)
чисто теоретически всё верно


 
jack128 ©   (2005-01-10 03:45) [3]


>case Form2.Part of
>
>    1:
>      begin
>       FPos := 0;
>      end;
>
>    2:
>      begin
>       FPos := FPartSize + 1024;
>      end;
>
>    3:
>      begin
>       FPos := FPartSize * 2 + 1024;
>      end;
>
>    4:
>      begin
>       FPos := FPartSize * 3 + 1024;
>      end;
>
>    5:
>      begin
>       FPos := FPartSize * 4 + 1024;
>      end;
>
>    end; {of case}

мда..
if Form2.Part = 1 then
 FPos := 0
else
 FPos := FPartSize * (Form2.Part - 1) + 1024;
     

Фёдор Мегатронов   (10.01.05 3:07) [2]
{этот ИФ нужен для того чтобы выполнилось условие в цикле REPEAT}
If (FPartSize mod irfBytesToRead ) <> 0
then
 begin

  Repeat
   Inc(irfBytesToRead);
  Until (FPartSize mod irfBytesToRead) = 0

 end;

А каким образом irfBytesToRead влияет на услови в until??

А вообще, что тот у тебя с логикой в программе нето.. Откуда 1024 взялось?? Что это такое??


 
Фёдор Мегатронов   (2005-01-10 03:58) [4]

на счёт условия
UNTIL ((FileSize(F) = FPartSize) может и не быть если (FPartSize mod irfBytesToRead ) <> 0 ... тоесть условие сработает только если >= или <= .. но вероятность того что оно будет = - 0,000001 процент...
если это условие не выполняеться, то гда первый кусок будет размером с весь исходный файл, а не с кусок.

поэтому я насильно размер считываемого буфера подгоняю так чтобы он делил без остатка.

эти 1024 там взялись потому что я уже просто незнаю почему ничего не работает ... и начал туда всё подряд припысывать.
там было и +1 и -1 и ещё черти чего 8).

Один раз я даже добился правильного размера файла ! но файл всёравно получался нерабочий.


 
jack128 ©   (2005-01-10 04:52) [5]

Вот примерно такой процедуркой ты можешь скачать часть файла

const
 // размер части, на которую мы делим наш файл
 FileSize = 64* 1024;
 // скачиваем файл из инета по 1024 байта
 BufSize = 1024;
var
 fExists: boolean;
 f: file;
 TotalToRead, TotalReaded: Integer;
 ToRead, Readed: Integer;
 UrlFileSize: Integer;
begin
 // PartNo - этот номер скачивамой части, начиная с 1
 FileName := "part" + IntToStr(PartNo) + ".part";
 AssignFile(f, FileName);
 fExists := FileExists(FileName);
 // Открываем файл на диске
 if fExists then
   reset(f, 1)
 else
   Rewrite(f, 1);
 try
   FPos := FileSize * (PartNo - 1) + System.FileSize(f);
   InternetSetFilePointer(UrlFile, FPos);
   // Определяем сколько данных нам нужно скачать
   if fExists then
     TotalToRead := FileSize - System.FileSize(f);
   else
     TotalToRead := FileSize;
   // Что бы не вылезать за границу файла
   TotalToRead := Min(InternetGetFileSize(UrlFile) - FPos, TotalToRead); // незнаю существует ли такая функция, если нет, то сам ж напиши, я в сетях не силен..
   TotalReaded := 0;
   // Выделяем буффер
   SetLength(Buffer, BuffSize);
   while (TotalReaded < TotalToRead) do
   begin
     ToRead := Min(BufSize, TotalToRead - TotalReaded);
     if not InternetReadFile(UrlFile, PChar(Buffer)^, ToRead, Readed) or (ToRead < Readed) then
       raise Exception.Create("Reading error");
     inc(TotalReaded, Readed);
   end;
 finally
   CloseFile(f);
 end;
end;


 
jack128 ©   (2005-01-10 04:54) [6]

Открытие/закрытие файла в инете, проверка Terminated, обработка исключений - это все на твой совести.



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

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

Наверх




Память: 0.5 MB
Время: 0.024 c
4-1101985427
Ana
2004-12-02 14:03
2005.01.23
Как отловить нажатие кнопки в окне чужого приложения?


1-1105049240
Deos
2005-01-07 01:07
2005.01.23
Отправить файл


1-1105332216
Ray Eagle
2005-01-10 07:43
2005.01.23
интеграция отчета из Rave Reports


1-1104947469
Sun bittern
2005-01-05 20:51
2005.01.23
Поток и обработка процедуры


3-1103625571
galexis
2004-12-21 13:39
2005.01.23
Ошибка Out Of Memory