Форум: "Основная";
Текущий архив: 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.04 c