File Ada-读取大文件

File Ada-读取大文件,file,ada,File,Ada,我正在构建一个HTTP服务器,主要是为了学习/好奇,我遇到了一个Ada中从未遇到过的问题。如果我尝试使用Direct_IO读取过大的文件,我会得到一个存储错误:堆栈溢出异常。这几乎从未发生过,但当我请求一个视频文件时,会抛出异常 所以我想到了一次读取和发送100万个字符的文件,但这会给我留下结束错误,因为大多数文件的长度不会精确到100万个字符。我也不完全确定我是否做对了,因为之前阅读整个文件已经足够了。以下是我编写的程序: procedure Send_File(Channel : GNAT.

我正在构建一个HTTP服务器,主要是为了学习/好奇,我遇到了一个Ada中从未遇到过的问题。如果我尝试使用Direct_IO读取过大的文件,我会得到一个存储错误:堆栈溢出异常。这几乎从未发生过,但当我请求一个视频文件时,会抛出异常

所以我想到了一次读取和发送100万个字符的文件,但这会给我留下结束错误,因为大多数文件的长度不会精确到100万个字符。我也不完全确定我是否做对了,因为之前阅读整个文件已经足够了。以下是我编写的程序:

procedure Send_File(Channel : GNAT.Sockets.Stream_Access; Filepath : String) is
    File_Size : Natural := Natural(Ada.Directories.Size (Filepath));
    subtype Meg_String is String(1 .. 1048576);
    package Meg_String_IO is new Ada.Direct_IO(Meg_String);
    Meg : Meg_String;
    File : Meg_String_IO.File_Type;
    Count : Natural := 0;
begin
    loop
        Meg_String_IO.Open(File, Mode => Meg_String_IO.In_File, Name => Filepath);
        Meg_String_IO.Read(File, Item => Meg);
        Meg_String_IO.Close(File);
        String'Write(Channel, Meg);
        exit when Count >= File_Size;
        Count := Count + 1048576;
    end loop;
end Send_File;
我想声明两个独立的Direct_IO包/字符串大小,其中一个长度为1048576,另一个长度为文件长度mod 1048576,但我不确定如何顺序使用这两个读卡器


感谢所有能提供帮助的人。

我会使用
Stream_IO
(),它允许您读取缓冲区,并告诉您实际读取了多少数据;看,

程序读取(文件:文件类型;
项目:输出\u元素\u数组;
最后:输出元素偏移量);
使用中描述的语义

读取操作从指定流传输流元素以填充数组项。元素被转移,直到项目长度元素被转移,或者直到到达流的末尾。如果传输了任何元素,则在last中返回最后传输的流元素的索引。否则,项目First-1将在Last中返回。仅当到达流的末尾时,Last小于Item'Last

过程发送文件(通道:GNAT.Sockets.Stream\u访问;
文件路径(字符串)为
文件:Ada.Streams.Stream\u IO.File\u类型;
缓冲区:Ada.Streams.Stream_元素_数组(1..1024);
最后:Ada.Streams.Stream_元素_偏移量;
使用类型Ada.Streams.Stream\u Element\u Offset;
开始
Ada.Streams.Stream_IO.Open(文件,
Mode=>Ada.Streams.Stream\u文件中的IO,
Name=>Filepath);
环
从文件中读取下一个缓冲区已满。Last接收读取的最后一个字节的索引;如果我们在这次读取中到达了文件的末尾,Last将小于Buffer'Last

Ada.Streams.Stream\u IO.Read(文件,项=>Buffer,Last=>Last);
写入实际读取的数据。如果文件的大小是缓冲区长度的倍数,则最后一次读取将不读取字节,并将返回最后一次0(缓冲区的First-1),因此这将写入缓冲区(1..0),即不读取字节

Ada.Streams.Write(Channel.all,缓冲区(1..Last));
读取的缓冲区未满的唯一原因是已到达文件末尾

在最后一次

(还要注意,最好在循环之外打开和关闭文件!)

我会使用
Stream_IO
(),它允许您读取缓冲区,并告诉您实际读取了多少数据;看,

程序读取(文件:文件类型;
项目:输出\u元素\u数组;
最后:输出元素偏移量);
使用中描述的语义

读取操作从指定流传输流元素以填充数组项。元素被转移,直到项目长度元素被转移,或者直到到达流的末尾。如果传输了任何元素,则在last中返回最后传输的流元素的索引。否则,项目First-1将在Last中返回。仅当到达流的末尾时,Last小于Item'Last

过程发送文件(通道:GNAT.Sockets.Stream\u访问;
文件路径(字符串)为
文件:Ada.Streams.Stream\u IO.File\u类型;
缓冲区:Ada.Streams.Stream_元素_数组(1..1024);
最后:Ada.Streams.Stream_元素_偏移量;
使用类型Ada.Streams.Stream\u Element\u Offset;
开始
Ada.Streams.Stream_IO.Open(文件,
Mode=>Ada.Streams.Stream\u文件中的IO,
Name=>Filepath);
环
从文件中读取下一个缓冲区已满。Last接收读取的最后一个字节的索引;如果我们在这次读取中到达了文件的末尾,Last将小于Buffer'Last

Ada.Streams.Stream\u IO.Read(文件,项=>Buffer,Last=>Last);
写入实际读取的数据。如果文件的大小是缓冲区长度的倍数,则最后一次读取将不读取字节,并将返回最后一次0(缓冲区的First-1),因此这将写入缓冲区(1..0),即不读取字节

Ada.Streams.Write(Channel.all,缓冲区(1..Last));
读取的缓冲区未满的唯一原因是已到达文件末尾

在最后一次

(还请注意,最好在循环之外打开和关闭文件!)

Awesome,我对此进行了一些研究,发现这将适用于大于缓冲区范围的文件,因此问题有望得到解决。不过,现在我有一个不同的问题。我正在测试的图像文件和视频无法正常发送。这看起来和我以前尝试使用Ada.Text_IO读取这些文件时遇到的问题一样。在这种情况下,我认为这是因为文件的编码方式不适合文本IO包。有什么想法吗?哎呀,没关系。那是我做错的另一件事,完全无关。非常感谢。给出答案的方式也很好。太棒了,我对它进行了一些研究,发现它适用于大于缓冲区范围的文件,所以这个问题就解决了