4

数MBのバイナリファイルの内容を読み込み、バッファに格納したいと考えています。これが私の関数プロトタイプです(必要に応じて変更できます):

procedure GET_BIN_CONTENT_FROM_PATH(PATH    : in UNBOUNDED_STRING;
                                    CONTENT : out UNBOUNDED_STRING);

これまで、Direct_IO パッケージを使用して 2 つの方法を試してきました。最初の方法では、ファイルを 1 文字ずつ読み取っていました。それは機能しましたが、非常に遅かったです。プロセスを高速化するために、ファイルを MB 単位で読み取ろうとしました。

procedure GET_BIN_CONTENT_FROM_PATH (PATH    : in UNBOUNDED_STRING;
                                     CONTENT : out UNBOUNDED_STRING) is

   BIN_SIZE_LIMIT : constant NATURAL := 1000000;
   subtype FILE_STRING is STRING (1 .. BIN_SIZE_LIMIT);
   package FILE_STRING_IO is new ADA.DIRECT_IO (FILE_STRING);
   FILE : FILE_STRING_IO.FILE_TYPE;
   BUFFER : FILE_STRING;

begin
   FILE_STRING_IO.OPEN (FILE, MODE => FILE_STRING_IO.IN_FILE,
                        NAME => TO_STRING (C_BASE_DIR & PATH));
   while not FILE_STRING_IO.END_OF_FILE (FILE) loop
      FILE_STRING_IO.READ (FILE, ITEM => BUFFER);
      APPEND (CONTENT, BUFFER);
   end loop;
   FILE_STRING_IO.CLOSE (FILE);
end GET_BIN_CONTENT_FROM_PATH;

残念ながら、ファイルの残りが 1MB 未満の場合、READ 操作は行われないようです。その結果、大きなファイル (>1MB) は切り捨てられ、小さなファイルはまったく読み取られません。これは、画像を扱うときに特に顕著です。

だから、私の質問は次のとおりです。バイナリファイルをすばやく完全に読み取る正しい方法は何ですか?

前もって感謝します。

4

4 に答える 4

6

Bin_Size を に等しくしAda.Directories.Size(my_file)、一度に読み取ります。

スタック割り当てには大きすぎる場合 (Storage_Error が発生します)、New で割り当て、名前変更のトリックを使用します。

my_image : bin_array renames my_image_ptr.all;

他に何も知る必要がないように...
しかし、それが数MBだけであれば、それは必要ありません.

于 2012-12-19T17:00:31.027 に答える
4

Ada.Streams.Stream_IO.ReadはStream_Element_Arrayを読み取り、最後に読み取られた要素を通知します。配列がいっぱいになっていない場合(ファイルの終わりに達したため)、Lastは。未満になりItem'Lastます。

Ada.Streams.Stream_Element'Size純粋主義者は、と同じではないかもしれないことに気付くでしょうCharacter'Sizeが、通常のプロセッサチップではそうなるので、に追加する前に、の使用部分と同じサイズのStream_Element_Arrayaの間でチェックなしの変換を行うことができます。StringContent

于 2012-12-19T18:15:59.910 に答える
0

他の人が述べたように、Ada.Streams.Stream_IO.Read が道です。私のシステムでまとめた例を次に示します。動的割り当てに使用できる十分なメモリがあると仮定すると、これはスタック サイズよりも大きなファイルを読み取ることができます。

Stream.IO.Read コードの内部を掘り下げていませんが、Stream_IO パッケージが (ヒープから割り当てられた) 4k のメモリ ブロックを使用して、読み取り操作をバッファリングしていると思われます。

with Ada.Directories;  use Ada.Directories;
with Ada.Direct_IO;
with Ada.Unchecked_Deallocation;
with Ada.Streams.Stream_IO;

procedure Read_Input_File is

   type Byte is mod 2 ** 8;
   type Byte_Array is array (File_Size range <>) of Byte;
   type Byte_Array_Access is access Byte_Array;
      
   procedure Delete is new Ada.Unchecked_Deallocation 
                           (Byte_Array, Byte_Array_Access);
 
   function Read_Binary_File (Filename : String)
      return Byte_Array_Access
   is
      package SIO renames Ada.Streams.Stream_IO;
 
      Binary_File_Size : File_Size := Ada.Directories.Size (Filename);
      Binary_File_Data : Byte_Array_Access; 
      S                : SIO.Stream_Access;   
      File             : SIO.File_Type;
 
   begin
      -- Allocate memory from the heap 
      Binary_File_Data := new Byte_Array (1 .. Binary_File_Size);
 
      SIO.Open (File, SIO.In_File, Filename);
      S := SIO.Stream (File);
 
      -- Read entire file into the buffer
      Byte_Array'Read (S, Binary_File_Data.all);
 
      SIO.Close (File);
 
      return Binary_File_Data;
   end;

   File_Data : Byte_Array_Access;

begin

   File_Data := Read_Binary_File ("File_Name.bin");

   -- Do something with data

   Delete (File_Data);

end Read_Input_File;
于 2021-05-21T22:09:15.850 に答える