Differences

This shows you the differences between two versions of the page.

Link to this comparison view

good_text_i_o_practice [2013/01/16 06:23]
sparre [Ada.Direct_IO + Ada.Directories] naming fix
good_text_i_o_practice [2013/01/16 08:08] (current)
sparre [POSIX.Memory_Mapping] It is not an _exact_ solution. ;-)
Line 20: Line 20:
    ​File_Name : String ​ := "​read_entire_file.adb";​    ​File_Name : String ​ := "​read_entire_file.adb";​
    ​File_Size : Natural := Natural (Ada.Directories.Size (File_Name));​    ​File_Size : Natural := Natural (Ada.Directories.Size (File_Name));​
- 
    ​subtype File_String ​   is String (1 .. File_Size);    ​subtype File_String ​   is String (1 .. File_Size);
    ​package File_String_IO is new Ada.Direct_IO (File_String);​    ​package File_String_IO is new Ada.Direct_IO (File_String);​
Line 82: Line 81:
  
 Using POSIX.Memory_Mapping is slightly faster than using Ada.Direct_IO,​ but you only really get a benefit from using memory mapping if you don't actually need the whole file, as the operating system only will copy in the parts of the file actually accessed by the application. Using POSIX.Memory_Mapping is slightly faster than using Ada.Direct_IO,​ but you only really get a benefit from using memory mapping if you don't actually need the whole file, as the operating system only will copy in the parts of the file actually accessed by the application.
 +
 +===== Process text file =====
 +
 +[[http://​rosettacode.org/​wiki/​File_IO|Task description]]. ​ In other words, read a file into a variable (possibly only a part of the file at a time) and write it out to another file.
 +
 +==== Line by line ====
 +
 +This solution reads from the file one line at a time.  One nice thing about this solution is that you easily can switch it to read from standard input - and possibly anything which your operating system considers a file.
 +
 +<code Ada>with Ada.Command_Line,​ Ada.Text_IO;​ use Ada.Command_Line,​ Ada.Text_IO;​
 +
 +procedure Read_File_Line_By_Line is
 +   ​Read_From : constant String := "​input.txt";​
 +   ​Write_To ​ : constant String := "​output.txt";​
 +
 +   ​Input,​ Output : File_Type;
 +begin
 +   begin
 +      Open (File => Input,
 +            Mode => In_File,
 +            Name => Read_From);
 +   ​exception
 +      when others =>
 +         ​Put_Line (Standard_Error,​
 +                   "​Can not open the file '"​ & Read_From & "'​. Does it exist?"​);​
 +         ​Set_Exit_Status (Failure);
 +         ​return;​
 +   end;
 +
 +   begin
 +      Create (File => Output,
 +              Mode => Out_File,
 +              Name => Write_To);
 +   ​exception
 +      when others =>
 +         ​Put_Line (Standard_Error,​
 +                   "​Can not create a file named '"​ & Write_To & "'​."​);​
 +         ​Set_Exit_Status (Failure);
 +         ​return;​
 +   end;
 +
 +   loop
 +      declare
 +         Line : String := Get_Line (Input);
 +      begin
 +         -- You can process the contents of Line here.
 +         ​Put_Line (Output, Line);
 +      end;
 +   end loop;
 +exception
 +   when End_Error =>
 +      Close (Input);
 +      Close (Output);
 +end Read_File_Line_By_Line;</​code>​
 +
 +This solution requires the Ada 2005 standard library to work.
 +
 +Notice how we avoid explicit checks for read access to the input file, creation/​write access to the output file, as well as availablity of more data to process. ​ Even if we put in explicit checks, we would still have to handle the same exceptions, as another application can change the state of the file system in parallel with this application,​ creating a race condition.
 +==== POSIX.Memory_Mapping ====
 +
 +The [[#​posixmemory_mapping|POSIX.Memory_Mapping]] solution for reading an entire file into memory practically solves this task as well.  Still, it has some limitations which may make it irrelevant for some purposes:
 +  * It only works for an actual file (i.e. one stored on a file system). ​ Specifically it doesn'​t work for standard input, pipes and TCP connections.
 +  * It is not line oriented (i.e. you have to parse line-breaks yourself).
 +  * It requires an implementation of the POSIX Ada API (for example FLORIST or WPOSIX).

Navigation