AdaPower Logged in as Guest
Ada Tools and Resources

Ada 95 Reference Manual
Ada Source Code Treasury
Bindings and Packages
Ada FAQ


Join >
Articles >
Ada FAQ >
Getting Started >
Home >
Books & Tutorials >
Source Treasury >
Packages for Reuse >
Latest Additions >
Ada Projects >
Press Releases >
Ada Audio / Video >
Home Pages >
Links >
Contact >
About >
Login >
Back
The Get_Line Mystery... continued (Martin Krischik)

-------------------------------------------------------------------------------
4) Reading Textfiles not written by Ada

This is all very well as long as the file was created by Ada.Text_IO. If the
file was created by other means - for example a text editor - than it might
be that the last line is missing a line terminator.

Remember the case where the line has exactly the length of the buffer. With
the first Get_Line your read all the characters, with the next Get_Line you
read 0 characters.

This works because with the first read reads all characters excluding the line 
terminator. The second one will read 0 characters and consume the line 
terminator.

However, in the special case of the last line missing a line terminator an 
"End_Of_File" exception might be raised instead.

The language lawyers think this is a compiler bug and an implicid line
terminator should be provided by the library. Still, this does not help us
and we need a workaround.

The following two functions have been taken from AdaCL (adacl.sf.net):

   package S_U     renames Ada.Strings.Unbounded;
   package IO      renames Ada.Text_IO;

   BufferSize : constant := 2000;

   function Get_Line (
      File : in IO.File_Type)
   return
      String
   is
      Buffer : String (1 .. BufferSize);
      Last   : Natural;
   begin
      IO.Get_Line (
         File => File,
         Item => Buffer,
         Last => Last);

      if Last < Buffer'Last then
         return Buffer (1 .. Last);
      elsif IO.End_Of_File (File) then
         return Buffer;
      else
         return Buffer & Get_Line (File);
      end if;
   end Get_Line;

   function Get_Line (
      File : in IO.File_Type)
   return
      S_U.Unbounded_String
   is
      Retval : S_U.Unbounded_String := S_U.Null_Unbounded_String;
      Item   : String (1 .. BufferSize);
      Last   : Natural;
   begin
      GetWholeLine :
      loop
         IO.Get_Line (
            File => File,
            Item => Item,
            Last => Last);

         S_U.Append (
            Source   => Retval,
            New_Item => Item (1 .. Last));

         exit GetWholeLine when Last < Item'Last
                      or   IO.End_Of_File (File);

      end loop GetWholeLine;

      return Retval;
   end Get_Line;

The workaround lies in checking for for End_Of_File after the Get_Line. If
End_Of_File is reached the last line has been read completly and is returned.
Any further attempt to read from that file will raise the "End_Of_File"
exception.

On Ada implemetation which provide an implicid line terminator the workaround 
will only consume a bit of performace for the unneded test but will do no
harm otherwise.

-------------------------------------------------------------------------------


(c) 1998-2004 All Rights Reserved David Botton