使用 Ada.Streams.Stream_IO.Read 的最大流文件 size/offset
Maximum size/offset of streamed File using Ada.Streams.Stream_IO.Read
我尝试从一个(可能)巨大的文件中读取特定的数据块(大约 4096 字节)。
在 GNAT 编译器中使用 Ada.Streams.Stream_IO.Read()
,我可以使用的最大偏移量是多少?也就是说,如果我想读取文件的最后 4 KB,使用
type Block_Array is array (1..4096) of Positive;
...
Ada.Streams.Stream_IO.Read(File, Block_Array, Last, Offset);
Offset 有多大(因此文件有多大)?
做一些研究,Offset
在 GNAT 中似乎被定义为 2 ** mod Standard'Address_Size
[1],在 32 位机器上将是 2^32
。我不太清楚这是指位、字节、千字节还是一些晦涩的倍数。
假设它表示字节,这是否意味着我可以处理的最大文件是 32 GB ((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;
可以看出,Count
的实际范围是实现定义的。因为我使用的是 GNAT 编译器(见上文),所以我检查了 [1]。这说明
The Standard I/O packages described in Annex A for
[...] Ada.Stream_IO [...]
are implemented using the C library streams facility; where
[...] All input/output operations use 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 GB ((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
在 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 位..应该足够了。
但是,正如 Alex 指出的那样,GNAT GPL 2014 有
type Stream_Element_Offset is range
-(2 ** (Standard'Address_Size - 1)) ..
+(2 ** (Standard'Address_Size - 1)) - 1;
这意味着,在 32 位计算机上,您被限制为 2 GB 的文件。
最新的 FSF GCC 源代码(与上面的 5.1.0 一样)已经更改;我们必须等到 GNAT GPL 2015 才能确定哪个是最终的。
更令人担忧的是,Ada.Streams.Stream_IO.Set_Position
(内部子程序)的 GNAT GPL 2014 代码是
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
参数 - 和朋友(我认为它必须,看看上面的代码)我认为编写自己的 Ada.Streams.Stream_IO
版本以始终使用 64 位函数并不会太难。可能最简单的方法是将其命名为 My_Stream_IO
并咬紧牙关关于使用内部 GNAT 单元的编译器警告,而不是尝试将其放入 Ada
层次结构中。
如果您想知道标量类型的范围,可以使用 <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;
如果您想访问比标准库支持的更大的文件,您可以导入操作系统函数以访问操作系统允许的最大文件。
从其他语言导入函数的详细信息在语言参考手册的附件 B 中指定。
我尝试从一个(可能)巨大的文件中读取特定的数据块(大约 4096 字节)。
在 GNAT 编译器中使用 Ada.Streams.Stream_IO.Read()
,我可以使用的最大偏移量是多少?也就是说,如果我想读取文件的最后 4 KB,使用
type Block_Array is array (1..4096) of Positive;
...
Ada.Streams.Stream_IO.Read(File, Block_Array, Last, Offset);
Offset 有多大(因此文件有多大)?
做一些研究,Offset
在 GNAT 中似乎被定义为 2 ** mod Standard'Address_Size
[1],在 32 位机器上将是 2^32
。我不太清楚这是指位、字节、千字节还是一些晦涩的倍数。
假设它表示字节,这是否意味着我可以处理的最大文件是 32 GB ((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;
可以看出,Count
的实际范围是实现定义的。因为我使用的是 GNAT 编译器(见上文),所以我检查了 [1]。这说明
The Standard I/O packages described in Annex A for [...] Ada.Stream_IO [...] are implemented using the C library streams facility; where [...] All input/output operations use 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 GB ((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
在 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 位..应该足够了。
但是,正如 Alex 指出的那样,GNAT GPL 2014 有
type Stream_Element_Offset is range
-(2 ** (Standard'Address_Size - 1)) ..
+(2 ** (Standard'Address_Size - 1)) - 1;
这意味着,在 32 位计算机上,您被限制为 2 GB 的文件。
最新的 FSF GCC 源代码(与上面的 5.1.0 一样)已经更改;我们必须等到 GNAT GPL 2015 才能确定哪个是最终的。
更令人担忧的是,Ada.Streams.Stream_IO.Set_Position
(内部子程序)的 GNAT GPL 2014 代码是
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
参数 - 和朋友(我认为它必须,看看上面的代码)我认为编写自己的 Ada.Streams.Stream_IO
版本以始终使用 64 位函数并不会太难。可能最简单的方法是将其命名为 My_Stream_IO
并咬紧牙关关于使用内部 GNAT 单元的编译器警告,而不是尝试将其放入 Ada
层次结构中。
如果您想知道标量类型的范围,可以使用 <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;
如果您想访问比标准库支持的更大的文件,您可以导入操作系统函数以访问操作系统允许的最大文件。
从其他语言导入函数的详细信息在语言参考手册的附件 B 中指定。