Ada Programming/Libraries/Ada.Streams.Stream_IO

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Ada. Time-tested, safe and secure.

This language feature is available from Ada 95 on.

Ada.Streams.Stream_IO is a unit of the Predefined Language Environment since Ada 95.

Description[edit]

“The packages Sequential_IO and Direct_IO have not proved to be sufficiently flexible for some applications because they process only homogenous files.” Ada 95 Rationale: Annex A.4.1 Stream Input and Output

“[Serialization is] the ability to write the complete state of an object (including any objects it refers to) to an output stream, and then recreate that object at some later time by reading its serialized state from an input stream.” Java in a Nutshell, David Flanagan, ,2nd ed, O’Reilly & Associates, Inc., 1997, p. 97.

A stream is an entity that can consume or produce elements of raw data, typically bytes.

Ada's Solution[edit]

Like Java, Ada 95 provides package Ada.Streams to allow a sequence of elements comprising values from possibly different types and allowing sequential access to these values.

  • procedure Write
  • procedure Read

Every type has a default encode–and–write procedure named by the attribute T'Write and a default read–and–decode procedure named by the attribute T'Read.

For example, suppose an input file mixed.data contains several groups of Float values in internal form, with each group preceded by an Integer value giving the number of values in the group. The following program writes the sum of each group in textual form to the standard output file (Ada as a Second Language, 2nd ed., Cohen, p 794 – corrected from Errata):

with Ada.Float_Text_IO;
with Ada.Streams.Stream_IO;

procedure Sum_Groups is

  Input_File   : Ada.Streams.Stream_IO.File_Type;
  Input_Stream : Ada.Streams.Stream_IO.Stream_Access;
  Group_Size   : Integer; -- Number of data items
  Sum          : Float; -- Sum of data items
  Next         : Float; -- Input data item

begin

  Ada.Streams.Stream_IO.Open(Input_File,
                             Ada.Streams.Stream_IO.In_File, 
                             "mixed.data");
  Input_Stream := Ada.Streams.Stream_IO.Stream(Input_File);

  Process_Group:
  while not Ada.Streams.Stream_IO.End_Of_File(Input_File) loop

    Integer'Read(Input_Stream, Group_Size);

    Sum := 0.0; -- Initialize sum of group

    Get_Group_Data:
    for I in 1..Group_Size loop
        Float'Read(Input_Stream, Next);
        Sum := Sum + Next;
    end loop Get_Group_Data;
    Ada.Float_Text_IO.Put(Sum);

  end loop Process_Group;
  Ada.Streams.Stream_IO.Close(Input_File);

end Sum_Groups;

Streams for Limited or User-defined Types[edit]

The programmer can override the 'Write and 'Read attributes for types whose default procedures do not provide the desired behavior. These types are typically access types or composite types with access–type subcomponents.

Typically, the programmer does not call the Read and Write procedures manipulating sequences of raw data directly. Instead, the programmer:

  1. Creates read and write procedures for types
  2. Associates procedures with corresponding attributes

Example[edit]

Encoding a date record (from Ada 95 Rationale, Annex A.4.1, p A–27)

type Day_Number is range 1..31;
type Month_Name is (January, February, March, April,
                    May, June, July, August,
                    September, October, November, December);
type Date_Record is
  record
    Day     : Day_Number;
    Month   : Month_Name;
    Year    : Integer;
  end record;

Then, the programmer creates an output file normally, and obtains access to associated date stream.

  Some_Date   : Date_Record;
  Date_File   : Ada.Streams.Stream_IO.File_Type;
  Date_Stream : Ada.Streams.Stream_IO.Stream_Access;
begin
  Ada.Streams.Stream_IO.Create(Date_File);
  Date_Stream := Ada.Streams.Stream_IO.Stream(Date_File);

To output the data, the programmer invokes the Write attribute for the Date_Record on the value of the date to be written:

Date_Record'Write(Date_Stream, Some_Date);

For a simple record such as Date_Record the predefined Write attribute simply calls the write attributes for each component in order.

The programmer can provide a version of Write to output the month name as, say, an integer:

First, define the date write procedure and associate 'Write attribute

procedure Date_Write(Stream : access Root_Stream_Type'Class;
                     Item   : in Date_Record) is
begin
  Integer'Write(Stream, Item.Day);
  Integer'Write(Stream, Month_Name'Pos(Item.Month) + 1);
  Integer'Write(Stream, Item.Year);
end Date_Write;
for Date_Record'Write use Date_Write;

Note that, instead of redefining Date_Record'Write, we could have simply redefined Month_Name'Write, and this would be called indirectly.

Specification[edit]

--                     Standard Ada library specification
--   Copyright (c) 2003-2018 Maxim Reznik <reznikmm@gmail.com>
--   Copyright (c) 2004-2016 AXE Consultants
--   Copyright (c) 2004, 2005, 2006 Ada-Europe
--   Copyright (c) 2000 The MITRE Corporation, Inc.
--   Copyright (c) 1992, 1993, 1994, 1995 Intermetrics, Inc.
--   SPDX-License-Identifier: BSD-3-Clause and LicenseRef-AdaReferenceManual
-- -------------------------------------------------------------------------

with Ada.IO_Exceptions;
package Ada.Streams.Stream_IO is

   type Stream_Access is access all Root_Stream_Type'Class;

   type File_Type is limited private;

   type File_Mode is (In_File, Out_File, Append_File);

   type    Count          is range 0 .. implementation_defined;
   subtype Positive_Count is Count range 1 .. Count'Last;
   --  Index into file, in stream elements.

   procedure Create (File : in out File_Type;
                     Mode : in File_Mode := Out_File;
                     Name : in String    := "";
                     Form : in String    := "");

   procedure Open (File : in out File_Type;
                   Mode : in File_Mode;
                   Name : in String;
                   Form : in String := "");

   procedure Close  (File : in out File_Type);
   procedure Delete (File : in out File_Type);
   procedure Reset  (File : in out File_Type; Mode : in File_Mode);
   procedure Reset  (File : in out File_Type);

   function Mode (File : in File_Type) return File_Mode;
   function Name (File : in File_Type) return String;
   function Form (File : in File_Type) return String;

   function Is_Open     (File : in File_Type) return Boolean;
   function End_Of_File (File : in File_Type) return Boolean;

   function Stream (File : in File_Type) return Stream_Access;
   --  Return stream access for use with T'Input and T'Output

   --  Read array of stream elements from file
   procedure Read (File : in  File_Type;
                   Item : out Stream_Element_Array;
                   Last : out Stream_Element_Offset;
                   From : in  Positive_Count);

   procedure Read (File : in  File_Type;
                   Item : out Stream_Element_Array;
                   Last : out Stream_Element_Offset);

   --  Write array of stream elements into file
   procedure Write (File : in File_Type;
                    Item : in Stream_Element_Array;
                    To   : in Positive_Count);

   procedure Write (File : in File_Type;
                    Item : in Stream_Element_Array);

   --  Operations on position within file

   procedure Set_Index(File : in File_Type; To : in Positive_Count);

   function Index(File : in File_Type) return Positive_Count;
   function Size (File : in File_Type) return Count;

   procedure Set_Mode(File : in out File_Type; Mode : in File_Mode);

   procedure Flush(File : in out File_Type);

   --  exceptions
   Status_Error : exception renames IO_Exceptions.Status_Error;
   Mode_Error   : exception renames IO_Exceptions.Mode_Error;
   Name_Error   : exception renames IO_Exceptions.Name_Error;
   Use_Error    : exception renames IO_Exceptions.Use_Error;
   Device_Error : exception renames IO_Exceptions.Device_Error;
   End_Error    : exception renames IO_Exceptions.End_Error;
   Data_Error   : exception renames IO_Exceptions.Data_Error;

private

   pragma Import (Ada, File_Type);

end Ada.Streams.Stream_IO;

See also[edit]

Wikibook[edit]

External examples[edit]

Ada Reference Manual[edit]

Ada 95[edit]

Ada 2005[edit]

Ada 2012[edit]

Open-Source Implementations[edit]

FSF GNAT

drake