我正在构建一个HTTP服务器,主要是出于学习/好奇的目的,我遇到了一个我从未在Ada中遇到过的问题 . 如果我尝试使用Direct_IO读取太大的文件,我会收到存储错误:堆栈溢出异常 . 这几乎从未发生,但是当我请求视频文件时,将抛出异常 .
所以我有了一次读取和发送1M个字符块的文件的想法,但是这给我留下了End Errors,因为大多数文件的长度都不是1M字符 . 我也不完全确定我是否正确,因为阅读整个文件之前一直都足够了 . 这是我写的程序:
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,但我不确定如何依次使用这两个读取器 .
感谢任何能提供帮助的人 .
1 回答
我使用
Stream_IO
(ARM A.12.1),它允许您读入缓冲区并告诉您实际读取了多少数据;见the second form of Read,使用ARM 13.13.1 (8)中描述的语义,
从File中读取下一个Buffer-full . Last接收读取的最后一个字节的索引;如果我们在此读取中到达文件结尾,则Last将小于Buffer'Last .
写下实际读取的数据 . 如果File的大小是Buffer'Length的倍数,则最后一次Read将不读取任何字节并返回Last of 0(Buffer'First - 1),因此这将写入Buffer(1 .. 0),即没有字节 .
读取少于Buffer-full的唯一原因是达到了文件结尾 .
(另请注意,最好在循环外打开和关闭文件!)