阿达 - 阅读大文件

时间:2015-10-13 01:37:14

标签: file ada

我正在构建一个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,而另一个长度为1048576,但是我不确定如何使用这两个读者顺序。

感谢任何可以提供帮助的人。

1 个答案:

答案 0 :(得分:7)

我使用Stream_IOARM A.12.1),它允许您读入缓冲区并告诉您实际读取了多少数据;见the second form of Read

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

使用ARM 13.13.1 (8)

中描述的语义
  

Read操作从指定的流传输流元素以填充数组Item。转移元素直到转移了Item'Length元素,或者直到达到流的末尾。如果传输了任何元素,则传输的最后一个流元素的索引将在Last中返回。否则,在Last中返回Item'First - 1。只有当到达流的末尾时,Last才会小于Item'Last。

procedure Send_File (Channel  : GNAT.Sockets.Stream_Access;
                     Filepath : String) is
   File   : Ada.Streams.Stream_IO.File_Type;
   Buffer : Ada.Streams.Stream_Element_Array (1 .. 1024);
   Last   : Ada.Streams.Stream_Element_Offset;
   use type Ada.Streams.Stream_Element_Offset;
begin
   Ada.Streams.Stream_IO.Open (File,
                               Mode => Ada.Streams.Stream_IO.In_File,
                               Name => Filepath);
   loop

从File中读取下一个Buffer-full。 Last接收读取的最后一个字节的索引;如果我们在此读取中到达文件结尾,则Last将小于Buffer'Last。

      Ada.Streams.Stream_IO.Read (File, Item => Buffer, Last => Last);

写入实际读取的数据。如果File的大小是Buffer'Length的倍数,则最后一次Read将不读取任何字节并返回Last of 0(Buffer'First - 1),因此这将写入Buffer(1 .. 0),即没有字节。 / p>

      Ada.Streams.Write (Channel.all, Buffer (1 .. Last));

读取低于Buffer-full的唯一原因是达到了文件结尾。

      exit when Last < Buffer’Last;
   end loop;
   Ada.Streams.Stream_IO.Close (File);
end Send_File;

(另请注意,最好打开和关闭文件循环外面!)

相关问题