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

Вниз

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

 
Фёдор Мегатронов   (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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.041 c
1-1105538319
Толян
2005-01-12 16:58
2005.01.23
Загрузка и сохранение таюлици ListView


4-1101736313
Dema-X
2004-11-29 16:51
2005.01.23
как по handle определить, какому приложению принадлежит окно


9-1097567163
delphiman
2004-10-12 11:46
2005.01.23
виртуальная комната


1-1104922438
Тов. Стёпка Жукин
2005-01-05 13:53
2005.01.23
TListBox


14-1104716032
Marat_Ch
2005-01-03 04:33
2005.01.23
к561





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский