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

Вниз

Delphi IO работает только с файлами до 2 Гб?   Найти похожие ветки 

 
Piter ©   (2006-09-30 14:23) [0]

Сидел, ломал голову тут почему моя программа не работает. Судя по всему, все эти reset / rewrite / blockread / blockwrite работают только с файлами до ~2 Гб (видимо, как раз "положительный" диапазон integer). Так ли это?

Не ожидал от borland такой подставы...


 
Джо ©   (2006-09-30 14:30) [1]

> Так ли это?

Тут проблема не в перечисленных процедурах, а в Seek (там позиция задается 32-битным параметром Longint) и вообще в позиционировании.


 
oxffff ©   (2006-09-30 14:40) [2]

Longint - signed 32-bit.

Не ожидал от borland такой подставы...?

Переходите на ASM.

А лучше на маш. коды 237,176 (ZX Spectrum Команда LDIR)


 
Джо ©   (2006-09-30 14:43) [3]

> [2] oxffff ©   (30.09.06 14:40)
> Переходите на ASM.

Зачем так строго? Достаточно использовать Win32 API с его SetFilePointer.


 
Джо ©   (2006-09-30 14:43) [4]

Да, и при чем тут ASM вообще?


 
oxffff ©   (2006-09-30 14:46) [5]

Открывайте Platform SDK: File Management Functions.

CreateFile, ReadFileEx, WriteFileEx, CloseHandle

Да Borland еще не написала своих оберток под OVERLAPPED IO, Memory Mapped Files и т.д. и т.п.

А нужно ли это.


 
Eraser ©   (2006-09-30 14:48) [6]

однако ж в TMemoryStream есть вот такая версия Seek.
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; virtual;
работает или нет - не проверял.


 
oxffff ©   (2006-09-30 14:50) [7]

Для меня лично это кажется странным.

>Piter
>Не ожидал от borland такой подставы...

push ebx
push 0
....
push eax
call [CreateFileA]

Тут никаких притензий к Borland


 
Джо ©   (2006-09-30 15:00) [8]

> [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.


 
guav ©   (2006-09-30 15:07) [9]

> однако ж в TMemoryStream есть вот такая версия Seek.
> function Seek(const Offset: Int64; Origin: TSeekOrigin):
> Int64; overload; virtual;

Думаю речь таки идёт о TFileStream . Или вы уже адресуете более 4 ГБ в 32 разрядном коде ? ;-)
Судя по исходникам, должна работать


 
Piter ©   (2006-09-30 15:14) [10]

Джо ©   (30.09.06 14:30) [1]
Тут проблема не в перечисленных процедурах, а в Seek (там позиция задается 32-битным параметром Longint) и вообще в позиционировании.


ага, наверное. Я не разбирался, у меня проблема была в том, что сделав Reset на таком большом файле EOF сразу показывала true.


 
Eraser ©   (2006-09-30 15:32) [11]

> [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 17:28) [12]

Eraser ©   (30.09.06 15:32) [11]

да это теперь очевидно... Просто странно, что borland лоханулись в этом вопросе...


 
Anatoly Podgoretsky ©   (2006-09-30 17:30) [13]

reset вообще не работает с размером.
А rewrite работает с размером 0 байт.
Вот blockread / blockwrite уже работают с байтиками, но и там нет размера, есть ограничение на одновременно прочитаное количество байтиков, так и Микрософт не в состоянии читать свыше 2 гб за раз, ограничение ОС.
Мне кажется, что автор пытается обойти это ограничение для Win32


 
Джо ©   (2006-09-30 17:36) [14]

> [13] Anatoly Podgoretsky ©   (30.09.06 17:30)
> Вот blockread / blockwrite уже работают с байтиками, но
> и там нет размера, есть ограничение на одновременно прочитаное
> количество байтиков, так и Микрософт не в состоянии читать
> свыше 2 гб за раз, ограничение ОС.

Дело не в том, а в том, что для file pointer в делфийском Seek предусмотрен Longint, а не Int64.


 
Anatoly Podgoretsky ©   (2006-09-30 18:12) [15]

Дело не в этом, ни одна из указаных функций не работает с размером файла и теоретически не имет ограничений. Другое дело, что BlockRead оставлен для совместимости со старыми программами, cушествует с 70 годов прошлого века, и нет никакого основания использовать его в новых, для этого предназначен TFileStream. Я бы понял если бы это использовалось для текстовых или не типизированых файлов, поскольку нет альтернативы, но для не типизированых файлов есть полноценная замена, а использовать старую - это себе вредить.
Про Seek в вопросе нет ни слова.


 
Anatoly Podgoretsky ©   (2006-09-30 18:20) [16]

Вот доказательство
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:22) [17]


> Не ожидал от borland такой подставы...

Подставу искать не там, есть более подходящие цели.


 
Anatoly Podgoretsky ©   (2006-09-30 18:23) [18]

Кстати у нас даже начинающие приводят код как неправильно сделано.


 
oxffff ©   (2006-09-30 18:37) [19]

> > [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:43) [20]

oxffff ©   (30.09.06 18:37) [19]
Это точно, к вопросу отношения не имеет. Пожелание наверно. А если так, то FileStream


 
jTommy   (2006-09-30 20:42) [21]

Провел небольшое исследование, и теперь ответственно заявляю: метод 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.


 
Джо ©   (2006-09-30 21:01) [22]

> [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.


 
Джо ©   (2006-09-30 21:01) [23]

Ну, лишние переменные убрать :)


 
jTommy   (2006-09-30 22:03) [24]


> Джо ©   (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.



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

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

Наверх




Память: 0.53 MB
Время: 0.067 c
2-1158753837
Darkwing
2006-09-20 16:03
2006.10.15
TIBQuery. Как сделать поиск (select, like) нечувствительным


15-1159256648
Sandman29
2006-09-26 11:44
2006.10.15
Коммерсант-Власть


2-1159615368
AriCK
2006-09-30 15:22
2006.10.15
2 listbox


2-1159264876
vegarulez
2006-09-26 14:01
2006.10.15
Вопрос про мышь и 2 монитора (раб. стола).


2-1159698030
redlord
2006-10-01 14:20
2006.10.15
listbox выводить текст разным цветом