2015-05-22 2 views
0

Я пытаюсь прочитать определенные блоки данных (около 4096 байт) из (возможно) огромного файла.Максимальный размер/смещение потокового файла с использованием Ada.Streams.Stream_IO.Read

Используя Ada.Streams.Stream_IO.Read() с компилятором GNAT, каково было бы максимальное смещение, которое я мог бы использовать? То есть, если бы я хотел, чтобы прочитать последние 4 килобайта файла, используя

type Block_Array is array (1..4096) of Positive; 
... 
Ada.Streams.Stream_IO.Read(File, Block_Array, Last, Offset); 

насколько велико может Смещение быть (и, следовательно, файл)?

Выполнение небольшого исследования, Offset, представляется в GNAT как 2 ** mod Standard'Address_Size [1], которое будет 2^32 на 32-битной машине. Мне не совсем понятно, если это относится к битам, байтам, килобайтам или даже к некоторым неясным кратным.

Предположим, что это означает байты, не означает ли это, что самый большой файл, который я мог бы обрабатывать, будет 32 гигабайта ((2^32*8)/1024^3) большой? Если да, то есть ли способ сделать это больше?


Так как это было предложено, чтобы я не проверил (язык) в справочном руководстве, здесь исследования, которые привели меня к этому вопросу в первую очередь:

В [2] read процедуры определяется как:

procedure Read (File : in File_Type; 
       Item : out Stream_Element_Array; 
       Last : out Stream_Element_Offset; 
       From : in Positive_Count); 

чуть дальше вверх:

type Count   is range 0 .. *implementation-defined*; 
subtype Positive_Count is Count range 1 .. Count'Last; 

в качестве одного с a, действительный диапазон Count - , определенный реализацией. Поскольку я использую компилятор GNAT (см. Выше), я проверил [1]. Это указывает, что

пакеты Standard I/O описаны в Приложении А для [...] Ada.Stream_IO [...] реализованы с использованием библиотеки C потоков объекта; где [...] Все операции ввода/вывода используют fread/fwrite.

В той же документации ниже

function fread 
    (buffer : voids; 
     size : size_t; 
     count : size_t; 
     stream : FILEs) 

где

type size_t is mod 2 ** Standard'Address_Size; 

Опять Standard'Address_Size бы 32 на 32-битной машине (я также проверил перед спрашивать, что это случай на моем компьютере). Я также по-прежнему не уверен, прочитав как справочное руководство по языку, так и документацию по внедрению GNAT, если Stream_Element_Offset относится к байтам или к чему-то другому.

Но опять же, если предположить, что это означает байты, не означает ли это, что самый большой файл, который я мог бы обрабатывать, будет 32 гигабайта ((2^32*8)/1024^3) большой? Если да, то есть ли способ сделать это больше?

[1]: The Implementation of Standard I/O - GNAT Reference Manual

[2]: Ada Reference Manual - A.12.1 The Package Streams.Stream_IO

+2

Не похоже, что вы изучили спецификацию пакета 'Ada.Streams.Stream_IO' в справочном руководстве по языку (раздел A.12.1). –

+0

@JacobSparreAndersen Ну, похоже, на самом деле это не так. См. Редактирование в моем вопросе. Кроме того, снисходительность никогда не помогает. Если есть что-то, что я пропустил (что, скорее всего, и почему я спрашиваю), пожалуйста, не стесняйтесь дать проницательный ответ. – alex

+0

32 гигабит, а не гигабайты. –

ответ

3

В Mac OS X, с FSF GCC 5.1.0, есть

procedure Read 
    (File : File_Type; 
    Item : out Stream_Element_Array; 
    Last : out Stream_Element_Offset; 
    From : Positive_Count); 

где

type Count is new Stream_Element_Offset 
    range 0 .. Stream_Element_Offset’Last; 

subtype Positive_Count is Count range 1 .. Count’Last;   --' 
-- Index into file, in stream elements 

и (в Ada.Streams)

type Stream_Element_Offset is new Long_Long_Integer; 

, которая составляет 64 бита .. должно быть достаточно.

Однако, Алекс указывает, GNAT GPL 2014 имеет

type Stream_Element_Offset is range 
    -(2 ** (Standard'Address_Size - 1)) .. 
    +(2 ** (Standard'Address_Size - 1)) - 1; 

, что означает, что на 32-битной машине, вы ограничены 2 гигабайт файлов.

Были изменены последние источники FSSS GCC (как и для 5.1.0 выше); нам придется подождать, пока GNAT GPL 2015 не увидит, что является окончательным.

В качестве дополнительной причиной для беспокойства, комар GPL 2014 код Ada.Streams.Stream_IO.Set_Position (внутренний) подпрограммы является

procedure Set_Position (File : File_Type) is 
    use type System.CRTL.long; 
    use type System.CRTL.ssize_t; 
    R : int; 
begin 
    if Standard'Address_Size = 64 then 
     R := fseek64 (File.Stream, 
        System.CRTL.ssize_t (File.Index) - 1, SEEK_SET); 
    else 
     R := fseek (File.Stream, 
        System.CRTL.long (File.Index) - 1, SEEK_SET); 
    end if; 

    if R /= 0 then 
     raise Use_Error; 
    end if; 
end Set_Position; 

в то время как версии GCC 5.1.0 (который не имеет альтернативных реализаций) является

procedure Set_Position (File : File_Type) is 
    use type System.CRTL.int64; 
    R : int; 
begin 
    R := fseek64 (File.Stream, System.CRTL.int64 (File.Index) - 1, SEEK_SET); 

    if R /= 0 then 
     raise Use_Error; 
    end if; 
end Set_Position; 

Если ваша система имеет fseek64() - или, возможно, fseeko(), который принимает off_t, а не long для параметра offset - и друзья (я думаю, что это Mu st, смотря на код выше) Я бы подумал, что не будет слишком сложно написать собственную версию Ada.Streams.Stream_IO, чтобы всегда использовать 64-битные функции. Наверное, проще всего называть его My_Stream_IO и вырезать зубы о предупреждениях компилятора при использовании внутренних блоков GNAT, а не пытаться сложить его в иерархию Ada.

+0

Это правда, но только для FSF GCC, а не GNAT, как в моем ответе. Поскольку Mac OS X является 64-разрядной только в течение очень долгого времени, теперь представляется логичным, чтобы она имела 64-битные переменные.Мне кажется, что на 64-битных машинах GNAT также позволял бы использовать такие огромные файлы, но, в частности, в 32-битных машинах, похоже, для сегодняшних довольно разумных файлов существует ограничение. – alex

+0

FSF GCC * есть * Gnat. Если вы используете какую-то другую сборку Gnat, это может быть полезно сказать - и следуйте подходу Саймона, чтобы понять, отличается ли ответ на используемую вами реализацию от Саймона. –

+0

@BrianDrummond А я этого не знал. Тогда FSF, вероятно, означает Free Software Foundation? Хорошо, тогда я использую 'gcc (GCC) 4.7.4 20140401 для GNAT GPL gpl-2014 (20140405)'. И для этой версии я подумал, что приведенные выше ссылки (используя добросовестно тот же подход, что и Симон) завершат мой «ответ». Это верно? – alex

0

Если вы хотите знать, радиус действия скалярного типа, вы можете получить доступ к минимальному и максимальному значению, используя <type>'First и <type>'Last:

with Ada.Text_IO; 

procedure Check_Range is 
    use Ada.Text_IO; 
    subtype Type_To_Check is Integer; 
begin 
    Put (Type_To_Check'Image (Type_To_Check'First)); 
    Put (" .. "); 
    Put (Type_To_Check'Image (Type_To_Check'Last)); 
    New_Line; 
end Check_Range; 
0

Если вы хотите получить доступ файлов большего размера, чем то, что стандартные библиотеки опор, вы можете импортировать функции операционной системы, предоставляя доступ к самым большим файлам, разрешенным вашей операционной системой.

Сведения о импортировании функций с других языков указаны в приложении B в справочном руководстве по языку.

Смежные вопросы