🖥 OS.IO.File Text File - JulTob/Ada GitHub Wiki

Being able to work with text files is the most basic requirement of any programming language. This is the next step above the “Hello world!” example. For the following example, extensive use was made from the following RosettaCode snippet, located here:

-- line_by_line.adb:
with Ada.Strings.Fixed;
with Ada.Text_IO;
procedure Line_By_Line is
  Filename   : String := "line_by_line.adb";
  File       : Ada.Text_IO.File_Type;
  Line_Count : Natural := 0;
begin
  Ada.Text_IO.Open(File => File,
                   Mode => Ada.Text_IO.In_File,
                   Name => Filename);
  while not Ada.Text_IO.End_Of_File(File) loop
    declare
      Line : String := Ada.Text_IO.Get_Line(File);
    begin
      if Ada.Strings.Fixed.Count(Line, "Ada") > 0
      then
        Line_Count := Line_Count + 1;
        Ada.Text_IO.Put_Line(Natural'Image(Line_Count) & ": " & Line);
      end if;
    end;
  end loop;
  Ada.Text_IO.Close(File);
end Line_By_Line;

Right after the begin keyword, the file is opened in order for it to be read. In this case, the application opens its own source code (sort of like how people look at a picture of where a person’s organs are located). There is one thing that you need to keep in mind and that is the file needs to exist, or else you will get an exception raised. The exception can be caught and handled, so feel free to adjust the preceding example in order to catch this exception. 2) while not Ada.Text_IO.End_Of_File(File) loop – This basically creates a loop which iterates over all of the lines – one by one – until the end of the file. 3) if Ada.Strings.Fixed.Count(Line, "Ada") > 0 – Here the number of “Ada” sub-­strings are counted. If it is greater than 0, then we have met the condition to keep going in the if statement and print out the line in question. 4) Ada.Text_IO.Close(File); – This will close the file that we opened. This is sometimes done automatically by default when the application finishes running by the operating system, but it makes sense to get into habit of doing this, even more so if you have many files open and do not want to create a condition where resources are not being deallocated.

Writing to a Text File

Let’s make things a little bit more complicated. Let’s write the contents of a record into a file. Here are the things that need to be accomplished in this example:

  1. Create a record that we can work with.
  2. Instantiate the record.
  3. Populate the record with default values.
  4. Create a procedure that will take the record and write its contents to a file of our choice.
-- write_record_to_file.adb:
with Ada.Strings.Unbounded;
with Ada.Text_IO;
procedure Write_Record_To_File is
  type Person_Rec is record
    Age        : Natural;
    First_Name : Ada.Strings.Unbounded.Unbounded_String;
    Last_Name  : Ada.Strings.Unbounded.Unbounded_String;
    -- True is for male and False is for female.
    Sex        : Boolean;
  end record;
  procedure Write_Person(
    Individual : in Person_Rec;
    Filename : in String) is
    F_Type : Ada.Text_IO.File_Type;
  begin
    -- open the file that I want, if it does not exist, create it.
    declare
    begin
      Ada.Text_IO.Open(
        File => F_Type,
        Mode => Ada.Text_IO.Out_File,
        Name => Filename);
    exception
      when Ada.Text_IO.Name_Error =>
        Ada.Text_IO.Create(
          File => F_Type,
          Mode => Ada.Text_IO.Out_File,
          Name => Filename);
    end;

write to the file.
    Ada.Text_IO.Put(
      File => F_Type,
      Item => Ada.Strings.Unbounded.To_String(Individual.First_Name));
    Ada.Text_IO.Put(
      File => F_Type,
      Item => "  ");
    Ada.Text_IO.Put_Line(
      File => F_Type,
      Item => Ada.Strings.Unbounded.To_String(Individual.Last_Name));
    Ada.Text_IO.Put_Line(
      File => F_Type,
      Item => Natural'Image(Individual.Age));
    if Individual.Sex = True
    then
      Ada.Text_IO.Put_Line(File => F_Type, Item => "Man");
    else
      Ada.Text_IO.Put_Line(File => F_Type, Item => "Woman");
    end if;
    -- close the file.
    Ada.Text_IO.Close(File => F_Type);
  end Write_Person;
  Jim_T  : Person_Rec;
  Mary_Y : Person_Rec;
begin
  -- assign values to the Jim_T instance.
  Jim_T.Age        := 43;
  Jim_T.First_Name := Ada.Strings.Unbounded.To_Unbounded_String("Jim");
  Jim_T.Last_Name  := Ada.Strings.Unbounded.To_Unbounded_
String("Thompson");
  Jim_T.Sex        := True;
  -- assign values to the Mary_Y instance.
  Mary_Y.Age        := 25;
  Mary_Y.First_Name := Ada.Strings.Unbounded.To_Unbounded_String("Mary");

  Mary_Y.Last_Name  := Ada.Strings.Unbounded.To_Unbounded_String("Yannis");
  Mary_Y.Sex        := False;
  Write_Person(Jim_T, "jim_file.txt");
  Write_Person(Mary_Y, "mary_file.txt");
end Write_Record_To_File;


Here is what this example does:

  1. At the very start of the declaration portion of Write_Record_To_ File procedure, a record specification is created.
  2. Next is the procedure – Write_Person – that is responsible for printing out the record to file. This is a somewhat verbose method, so let’s take it apart piece by piece: a) The procedure takes a copy of the instance of a record and the name of the file that will be created for storage. b) Right before the begin keyword, the File_Type object is created; this is important later on in the method. c) This is where things get interesting. All of the concepts described here have been covered already in this book. The declare block is where a separate scope level is created, perfect for working with our file. If the file that we need is not created, then an exception is thrown. Without an exception, we could end up halting our application in an inconvenient way. With this declare block, an unforeseen situation can be easily handled (in this case, a new output file will be created and assigned the file pointer to the F_Type variable). d) This next chunk of code is where we output the record to a text file. Basically, you are taking the contents of the record and then turning all of them into the string type before writing to file. On the first line, you will see the first and last name. On the second line, there will be the age of the person. On the last line, you will see whether the person in question is a man or woman. In this case, the inputs to the Put_Line procedure were explicitly specified for instructive purposes. e) The last thing that we do is close the file.
  3. If you look at the body of Write_Record_To_File, things are pretty simple. You instantiate the individual records and write each to file. The preceding example can be fairly confusing. If things do not make much sense, you are encouraged to place Put_Line statements and see how the logic of the application flows. This might be a little bit challenging, but make a small application that will read in the files that were generated line by line and store the contents of it as a series of strings. Try it. You will have a much better grasp of what is going on.