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

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.282 c
15-1158895814
страстно жаждущий все знать
2006-09-22 07:30
2006.10.15
докумсентация по 1с


15-1157534717
Stexen
2006-09-06 13:25
2006.10.15
Turbo delphi


2-1159531313
Sergey_b
2006-09-29 16:01
2006.10.15
Где нажата кнопка


2-1159345624
RusTim
2006-09-27 12:27
2006.10.15
TreeView c CheckBox


2-1159520325
tyo
2006-09-29 12:58
2006.10.15
запись в базу через DBGrid





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