![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Delphi IO работает только с файлами до 2 Гб?
Piter © (2006-09-30 14:23:00)Сидел, ломал голову тут почему моя программа не работает. Судя по всему, все эти reset / rewrite / blockread / blockwrite работают только с файлами до ~2 Гб (видимо, как раз "положительный" диапазон integer). Так ли это?
Не ожидал от borland такой подставы...
jTommy (2006-09-30 22:03:00) [1]
> Джо © (30.09.06 21:01) [22]
> Fs.Seek(1,soFromEnd);
Так она работает. Странно, что без разговоров устанавливает указатель за пределы файла, согласно справке смещение должно быть меньше или равно нулю.
Но если вызвать так:
SeekResult:=Fs.Seek(1,soFromEnd);
То результат в SeekResult будет неправильный. Это не нормально.
И все-таки, если я пытаюсь установить указатель от начала файла:
fpos:=любое смещение;
fs.Seek(fpos, soFromBeginning);
WriteLn(fs.Position);
за пределом в 2.1Гб fs.Position возвратит размер_файла-1, а за пределом 4.2Гб - значение около 250-375Мб.
Более того, если скомпилировать с проверкой границ(Range Checking) на вызове fs.Seek случиться исключение ERangeError.
Джо (2006-09-30 21:01:00) [2]Ну, лишние переменные убрать :)
Джо (2006-09-30 21:01:00) [3]> [21] jTommy (30.09.06 20:42)
Неправильно тестируем, товарищ :)Попробуйте следующим образом:
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils,
Classes;
var
Fs: TFileStream;
SeekResult: Int64;
Position: Int64;
begin
// Файл ~4 Гб
Fs := TFileStream.Create('J:\pub\video\hdtv\The.Shawshank.R.1280x720.HDTVRip.XviD.AC3-5.1_Eng+Rus.(www.rusdivx.ee).cd1.avi',fmOpenRead);
try
Position := 1;
Fs.Seek(1,soFromEnd);
WriteLn (Fs.Position);
ReadLn;
finally
Fs.Free
end;
end.
jTommy (2006-09-30 20:42:00) [4]Провел небольшое исследование, и теперь ответственно заявляю: метод Seek класса TFileStream неправильно работает с файлами больше 2Гб :(.
Еще проверял копирование - естественно с этим все в порядке, копирует один в один.
Программа пробует установить указатель на позицию размер_файла-8мб.
Код программы:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
Const
szBuffer = 8388608; // 8mb
Var
fsIN: TFileStream;
fpos: int64;
begin
fsIN:=TFileStream.Create(ParamStr(1), fmOpenRead);
fpos:=fsIN.Seek(fsIN.Size-szBuffer, soFromBeginning);
WriteLn('Need position: ',fsIN.Size-szBuffer,' Seek result: ',fpos);
fsIN.Free;
end.
Результаты работы (в байтах):
Need position: 519.129.088 Seek result: 519.129.088
Need position: 4.282.613.760 Seek result: -1
Need position: 4.653.842.432 Seek result: 358.875.136
P.S.: файловая система естественно - NTFS.
Anatoly Podgoretsky (2006-09-30 18:43:00) [5]oxffff © (30.09.06 18:37) [19]
Это точно, к вопросу отношения не имеет. Пожелание наверно. А если так, то FileStream
oxffff (2006-09-30 18:37:00) [6]> > [5] oxffff © (30.09.06 14:46)
> > Открывайте Platform SDK: File Management Functions.
> >
> > CreateFile, ReadFileEx, WriteFileEx, CloseHandle
>
> Этим-то как раз абсолютно фиолетов размер файла. Точно так
> же, как и AssignFile,Reset, CloseFile.
Что то я тебя не понял.
Anatoly Podgoretsky (2006-09-30 18:23:00) [7]Кстати у нас даже начинающие приводят код как неправильно сделано.
Anatoly Podgoretsky (2006-09-30 18:22:00) [8]
> Не ожидал от borland такой подставы...
Подставу искать не там, есть более подходящие цели.
Anatoly Podgoretsky (2006-09-30 18:20:00) [9]Вот доказательство
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
const
Chunk = 1000000;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
end;
TAr = Array [1..Chunk] of byte;
var
Form1: TForm1;
f: file of Byte;
Ar: TAr;
Tr: Integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
ReadBytes: Int64;
begin
AssignFile(f, 'c:\Temp\1');
Reset(f);
ReadBytes := 0;
while True do begin
BlockRead(f, ar, Chunk, Tr);
ReadBytes := ReadBytes + Tr;
Label2.Caption := FormatFloat(',0', ReadBytes);
Application.ProcessMessages;
if ReadBytes < Chunk then Exit;
end;
end;
end.
Label2.Caption := 5 868 773 384
Как видим это больше 2 гб и даже больше 4 гб!!!
Борланд невинно оболган
Anatoly Podgoretsky (2006-09-30 18:12:00) [10]Дело не в этом, ни одна из указаных функций не работает с размером файла и теоретически не имет ограничений. Другое дело, что BlockRead оставлен для совместимости со старыми программами, cушествует с 70 годов прошлого века, и нет никакого основания использовать его в новых, для этого предназначен TFileStream. Я бы понял если бы это использовалось для текстовых или не типизированых файлов, поскольку нет альтернативы, но для не типизированых файлов есть полноценная замена, а использовать старую - это себе вредить.
Про Seek в вопросе нет ни слова.
Джо (2006-09-30 17:36:00) [11]> [13] Anatoly Podgoretsky © (30.09.06 17:30)
> Вот blockread / blockwrite уже работают с байтиками, но
> и там нет размера, есть ограничение на одновременно прочитаное
> количество байтиков, так и Микрософт не в состоянии читать
> свыше 2 гб за раз, ограничение ОС.
Дело не в том, а в том, что для file pointer в делфийском Seek предусмотрен Longint, а не Int64.
Anatoly Podgoretsky (2006-09-30 17:30:00) [12]reset вообще не работает с размером.
А rewrite работает с размером 0 байт.
Вот blockread / blockwrite уже работают с байтиками, но и там нет размера, есть ограничение на одновременно прочитаное количество байтиков, так и Микрософт не в состоянии читать свыше 2 гб за раз, ограничение ОС.
Мне кажется, что автор пытается обойти это ограничение для Win32
Piter (2006-09-30 17:28:00) [13]Eraser © (30.09.06 15:32) [11]
да это теперь очевидно... Просто странно, что borland лоханулись в этом вопросе...
Eraser (2006-09-30 15:32:00) [14]> [9] guav © (30.09.06 15:07)
ну да, я имел ввиду именно TFileStream :)
> [10] Piter © (30.09.06 15:14)
тогда думаю стОит отказаться от консольных функций и использовать либо TFileStream, либо функции типа FileOpen, FileRead и т.п. на который и построен TFileStream, лобо вообще использовать Win API напрямую.
Piter (2006-09-30 15:14:00) [15]Джо © (30.09.06 14:30) [1]
Тут проблема не в перечисленных процедурах, а в Seek (там позиция задается 32-битным параметром Longint) и вообще в позиционировании.
ага, наверное. Я не разбирался, у меня проблема была в том, что сделав Reset на таком большом файле EOF сразу показывала true.
guav (2006-09-30 15:07:00) [16]> однако ж в TMemoryStream есть вот такая версия Seek.
> function Seek(const Offset: Int64; Origin: TSeekOrigin):
> Int64; overload; virtual;
Думаю речь таки идёт о T FileStream . Или вы уже адресуете более 4 ГБ в 32 разрядном коде ? ;-)
Судя по исходникам, должна работать
Джо (2006-09-30 15:00:00) [17]> [6] Eraser © (30.09.06 14:48)
> однако ж в TMemoryStream есть вот такая версия Seek.
> function Seek(const Offset: Int64; Origin: TSeekOrigin):
> Int64; overload; virtual;
> работает или нет - не проверял.
Работает.
> [5] oxffff © (30.09.06 14:46)
> Открывайте Platform SDK: File Management Functions.
>
> CreateFile, ReadFileEx, WriteFileEx, CloseHandle
Этим-то как раз абсолютно фиолетов размер файла. Точно так же, как и AssignFile,Reset, CloseFile.
oxffff (2006-09-30 14:50:00) [18]Для меня лично это кажется странным.
>Piter
>Не ожидал от borland такой подставы...
push ebx
push 0
....
push eax
call [CreateFileA]
Тут никаких притензий к Borland
Eraser (2006-09-30 14:48:00) [19]однако ж в TMemoryStream есть вот такая версия Seek.
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; virtual;
работает или нет - не проверял.
oxffff (2006-09-30 14:46:00) [20]Открывайте Platform SDK: File Management Functions.
CreateFile, ReadFileEx, WriteFileEx, CloseHandle
Да Borland еще не написала своих оберток под OVERLAPPED IO, Memory Mapped Files и т.д. и т.п.
А нужно ли это.