I would like to read the content of a binary file of several MB and store it into a buffer. Here's my function prototype (I can change it if needed):
procedure GET_BIN_CONTENT_FROM_PATH(PATH : in UNBOUNDED_STRING;
CONTENT : out UNBOUNDED_STRING);
Until now I've tried two methods, both using the Direct_IO package. In the first method, I was reading the file character by character; it worked, but it was awfully slow. In order to speed up the process, I tried to read the file MB by 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;
Unfortunately, it seems that the READ operation won't happen if there is less than 1MB remaining in the file. As a result, big files (>1MB) get truncated, and little ones are not read at all. It's especially visible when working on images.
So, my question is: What's the correct method to read a binary file both quickly and entirely?
Thanks in advance.
Make the Bin_Size equal to Ada.Directories.Size(my_file)
, and read it in one go.
If it's too big for stack allocation (you'll get Storage_Error) allocate it with New, and use the rename trick
my_image : bin_array renames my_image_ptr.all;
so that nothing else need know...
But if it's only a few MB, that won't be necessary.
Ada.Streams.Stream_IO.Read reads into a Stream_Element_Array and tells you the last element read; if the array isn't filled (because you've reached the end of file), Last
will be less than Item'Last
.
A purist will note that Ada.Streams.Stream_Element'Size
may not be the same as Character'Size
, but for any normal processor chip it will be, so you can do unchecked conversion between the used part of the Stream_Element_Array
and a String
of the same size before appending to your Content
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With