Fluxuri de intrare ieşire

 

Fluxurile de intrare \ ieşire reprezintă mecanismele prin intermediul cărora programele java pot citi \ scrie date de la şi către diverse destinaţii (fişiere, alte programe, memorie, resurse de reţea, dispozitive etc.).

 

Un flux este un canal de comunicaţie unidirecţional prin intermediul căruia datele pot fi citite sau scrise.

 

Prin intermediul fluxurilor de intrare datele sunt citite. Prin intermediul fluxurilor de ieşire datele sunt transmise către o destinaţie.

 

Figura 1. Fluxurile de intrare şi ieşire.

 

În java există două tipuri de fluxuri: fluxuri orientate pe byte şi fluxuri orientate pa caracter.

 

Fluxurile orientate pe byte sunt folosite in general pentru scrierea şi citirea de date binare (imagini, sunete, obiecte, etc), array-uri de date.

 

 

Figura 1. Fluxurile din citire \ scriere orientate pe byte.

 

Fluxurile de citire orientate pe byte au la bază clasa InputStream iar fluxurile de scriere au la baza clasa OutputStream.

 

Fluxurile orientate pe caracter au fost introduse in versiunea 1.1. a java şi sunt destinate pentru manipularea şirurilor de caractere (scrierea şi citirea se face pe 16 biţi).

 

Figura 2. Fluxurile de citire \ scriere orientate pe caracter.

 

Fluxurile de citire orientate pe caracter au la bază clasa Reader iar fluxurile de scriere au la baza clasa Writer.

 

Pentru majoritatea programelor scrierea si citirea datelor se va face prin intermediul fluxurilor de caractere deoarece acestea permit manipularea caracterelor Unicode (16-biti), În timp ce fluxurile de octeţi permit doar lucrul pe 8 biţi.

Utilizare fluxurilor de intrare / ieşire

 

Aplicaţia următore exemplifică modul în care fluxurile de intrare ieşire pot fi folosite pentru scrierea şi citirea de date din cadrul aplicaţiilor java.

 

import java.io.*;

public class IOStreamDemo {

 

      public static void main(String[] args)

        throws IOException {

          // 1. Reading input by lines:

          BufferedReader in = new BufferedReader(

            new FileReader(".project"));

          String s, s2 = new String();

          while((s = in.readLine())!= null)

            s2 += s + "\n";

          in.close();

 

          // 1b. Reading standard input:

          BufferedReader stdin = new BufferedReader(

            new InputStreamReader(System.in));

          System.out.print("Enter a line:");

          System.out.println(stdin.readLine());

 

          // 2. Input from memory

          StringReader in2 = new StringReader(s2);

          int c;

          while((c = in2.read()) != -1)

            System.out.print((char)c);

 

          // 3. Formatted memory input

          try {

            DataInputStream in3 = new DataInputStream(

              new ByteArrayInputStream(s2.getBytes()));

            while(true)

              System.out.print((char)in3.readByte());

          } catch(EOFException e) {

            System.err.println("End of stream");

          }

 

          // 4. File output

          try {

            BufferedReader in4 = new BufferedReader(

              new StringReader(s2));

            PrintWriter out1 = new PrintWriter(

              new BufferedWriter(new FileWriter("IODemo.out")));

            int lineCount = 1;

            while((s = in4.readLine()) != null )

              out1.println(lineCount++ + ": " + s);

            out1.close();

          } catch(EOFException e) {

            System.err.println("End of stream");

          }

 

          // 5. Storing & recovering data

          try {

            DataOutputStream out2 = new DataOutputStream(

              new BufferedOutputStream(

                new FileOutputStream("Data.txt")));

            out2.writeDouble(3.14159);

            out2.writeUTF("That was pi");

            out2.writeDouble(1.41413);

            out2.writeUTF("Square root of 2");

            out2.close();

            DataInputStream in5 = new DataInputStream(

              new BufferedInputStream(

                new FileInputStream("Data.txt")));

            // Must use DataInputStream for data:

            System.out.println(in5.readDouble());

            // Only readUTF() will recover the

            // Java-UTF String properly:

            System.out.println(in5.readUTF());

            // Read the following double and String:

            System.out.println(in5.readDouble());

            System.out.println(in5.readUTF());

          } catch(EOFException e) {

            throw new RuntimeException(e);

          }

 

          // 6. Reading/writing random access files

          RandomAccessFile rf =

            new RandomAccessFile("rtest.dat", "rw");

          for(int i = 0; i < 10; i++)

            rf.writeDouble(i*1.414);

          rf.close();

          rf = new RandomAccessFile("rtest.dat", "rw");

          rf.seek(5*8);

          rf.writeDouble(47.0001);

          rf.close();

          rf = new RandomAccessFile("rtest.dat", "r");

          for(int i = 0; i < 10; i++)

            System.out.println("Value " + i + ": " +

              rf.readDouble());

          rf.close();

 

        }

      } //.

Fluxuri standard de intrare / ieşire

 

În cadrul clasei System sunt definite fluxurile standard de intrare / ieşire System.in (in este un atribut static de tip InputStream definit în cadrul clasei System) şi System.out (out este un atribut static de tip OutputStream definit în cadrul clasei System) care sunt conectate în mod implicit la ecran respectiv tastatură. Exemplu următor prezintă modul în care poate fi folosit fluxul de intrare standard pentru citirea datelor. Pe lângă aceste două fluxuri în cadrul clasei System este definit şi fluxul err (atribut static de tip OutputStream definit în cadrul clasei System) care poate fi folosit pentru raportarea mesajelor de eroare.

 

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.util.*;

 

public class StandardIOExemplu {

     

      static String sortChars(String s){

            char[] a = s.toCharArray();

            Arrays.sort(a);

            return new String(a);

      }

     

      public static void main(String[] args) {

           

            try{

           BufferedReader fluxIn = new BufferedReader(new InputStreamReader(System.in));

           String linie = "";

                 do{

                   System.out.print(">");

                   linie = fluxIn.readLine();

                   System.out.println("result:"+sortChars(linie));

                 }while(linie.indexOf("end")==-1);    

            }catch(Exception e){

                  e.printStackTrace();

                  System.err.println("Eroare :"+e.getMessage());

 

            }

      }

}

 

Fluxurile standard pot fi redirectate folosind metodele setOut(), setIn() şi setErr() din cadrul clasei System.

 

import java.io.*;

class Redirectare {

      public static void main(String[] args) {

            try {

                  BufferedInputStream in = new BufferedInputStream(

                        new FileInputStream(".project"));

                  PrintStream out = new PrintStream(new BufferedOutputStream(

                        new FileOutputStream("test.out")));

                  System.setIn(in);

                  System.setOut(out);

                  System.setErr(out);

 

                  BufferedReader br = new BufferedReader(

                              new InputStreamReader(System.in));

                  String s;

                  while((s = br.readLine()) != null)

                        System.out.println(s);

                  out.close();

            } catch(IOException e) {

                  e.printStackTrace();

            }

      }

}

 

Serializarea obiectelor

 

Serializarea este macanismul prin care starea obiectelor poate fi citită din memorie şi trimisă printr-un flux către o destinaţie (o altă aplicaţie, fişier, reţea, etc.). Procesul invers prin care un obiect este reîncărcat în memorie prin citirea acestuia dintr-un flux se numeşte deserializare. Pentru serilaizarea şi deserializarea obiectelor limbajul java pune la dispoziţie fluxurile ObjectInputStream şi ObjectOutputStream.

 

import java.util.*;

import java.io.*;

 

public class SerializareExemplu {

      public static void main(String[] args) throws Exception{

            AlienFactory f = new AlienFactory();

           

            Alien a = f.createAlien("axx");

            Alien b = f.createAlien("abb");

           

            f.freezAlien(a,"aliena.dat");

            f.freezAlien(b,"alienb.dat");

           

            Alien x = f.unfreezAlien("alienb.dat");

            Alien y = f.unfreezAlien("aliena.dat");

           

            System.out.println(x);

            System.out.println(y);

      }

}//.class

 

class AlienFactory{

      Alien createAlien(String name){

            Alien z = new Alien(name);

            System.out.println(z+" is alive.");

            return z;

      }

     

      void freezAlien(Alien a, String storeRecipientName) throws IOException{

            ObjectOutputStream o =

              new ObjectOutputStream(

                new FileOutputStream(storeRecipientName));

           

            o.writeObject(a);

            System.out.println(a+":I'll be back.");

      }

     

      Alien unfreezAlien(String storeRecipientName) throws IOException, ClassNotFoundException{

             ObjectInputStream in =

                    new ObjectInputStream(

                      new FileInputStream(storeRecipientName));

             Alien x = (Alien)in.readObject();

             System.out.println(x+":I'm back.");

             return x;

      }

     

}//.class

 

 

class Alien implements Serializable{

      String name;

      transient int id;

     

      public Alien(String n) {

            this.name = n;

            id =  (int)(Math.random()*100);

      }

      public void move(){System.out.println("Alien is moving."+this);}

      public String toString(){return "[alien="+name+":id="+id+"]";}

}//.class

 

Pentru implementarea mecanismului de serializare / deserializare se poate folosi şi interfaţa Externalizable ce permite controlul mai fin al procesului de salvare şi încărcare a obiectelor. Această interfaţă extinde interfaţa Serializable şi defineşte metodele writeExternal() şi readExternal() în cadrul cărora trebui implementat codul pentru scrierea şi citire obiectelor. Clasa ce implementează această interfaţă trebuie obligatoriu să aibă definit constructorul implicit (având specificatorul de acces public).

 

Dacă se doreşte ca un anumit atribut al unui obiect serializat să nu fie salvat atunci se poate folosi cuvântul cheie transient în faţa declaraţiei atributului respecitv.

 

package isp.fluxuri.serializare;

 

import java.util.*;

import java.io.*;

 

public class SerializareExemplu2 {

           

public static void main(String[] args) {

      Tren tr = new Tren();

      Locomotiva l = new Locomotiva("XYZ", new Engine("diesel"));

      Vagon v1 = new Vagon(1,20);

      Vagon v2 = new Vagon(2,89);

      Vagon v3 = new Vagon(3,53);

     

      tr.addVagon(v1);tr.addVagon(v2);tr.addVagon(v3);

      tr.addLocomotiva(l);

     

      System.out.println(tr);

     

      tr.save("trenX");

     

      try {

            Tren t2 = Tren.load("trenX");

            System.out.println(t2);

      } catch (IOException e) {

            e.printStackTrace();

      } catch (ClassNotFoundException e) {

            e.printStackTrace();

      }

     

}

 

}

 

class Tren implements Serializable{

      LinkedList t = new LinkedList();

      transient int id;

     

      Tren(){

            id = (int)(Math.random()*1000);

      }

     

      void addVagon(Vagon v){

            t.addLast(v);

      }

     

      void addLocomotiva(Locomotiva e){

            t.addFirst(e);

      }

     

      void save(String fileName) {

            try {

                  ObjectOutputStream o =

                    new ObjectOutputStream(

                      new FileOutputStream(fileName));

                  o.writeObject(this);   

                  System.out.println("Tren salvat in fisier");

            } catch (IOException e) {

                  System.err.println("Trenul nu poate fi scris in fisiser.");

                  e.printStackTrace();

            }

           

      }

     

      static Tren load(String fileName) throws IOException, ClassNotFoundException {     

                  ObjectInputStream in =

                    new ObjectInputStream(

                      new FileInputStream(fileName));

                  Tren t = (Tren)in.readObject();    

                  return t;  

      }

     

      public String toString(){

            String x="Tren ID="+id+" ";

            for (Iterator i = t.iterator(); i.hasNext();) {

                  Object element = (Object) i.next();

                  x+=element;

            }

            return x;

      }    

}

 

class Vagon implements Externalizable{

      int nr;

      int nrPasageri;

     

      public Vagon(){}

     

      public Vagon(int i,int p) {

            nr=i;

            nrPasageri = p;

      }

 

      @Override

      public String toString() {

            return "<"+nr+" pasageri="+nrPasageri+">";

      }

 

      public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

            nr = in.readInt();

            nrPasageri=in.readInt();

      }

 

      public void writeExternal(ObjectOutput out) throws IOException {

            out.writeInt(nr);

            out.writeInt(nrPasageri);

      }

}

 

class Locomotiva implements Serializable{

      String marca;

      Engine e;

     

      /**

       * @param marca

       * @param e

       */

      public Locomotiva(String marca, Engine e) {

            this.marca = marca;

            this.e = e;

      }

     

      @Override

      public String toString() {

            return "[Locomotiva"+marca+" "+e+"]";

      }

 

}

 

class Engine implements Serializable{

      String tip;

      public Engine(String t) {

            tip = t;

      }

      @Override

      public String toString() {

            return "-"+tip+"-";

      }

}

 

Fluxuri de tip pipe

 

Fluxurile de tip pipe sunt folosite pentru a trimite date intre două componente ale aceluiaşi program. Utilitatea acestor tipuri de fluxuri va deveni evidentă în momentul în care se va discuta despre fire de execuţie şi aplicaţii multifir. Limbajul java permite construirea de pipe-uri orientate pe byte folosind clasele PipedInputStream / PipedOutputStream şi fluxuri orientate pe caracter folosind clasele PipedReader / PipedWriter.

 

import java.io.*;

 

public class Piped2Example {

public static void main(String[] args) {

      try{ 

            PipedReader in = new PipedReader();

            PipedWriter out = new PipedWriter();

            in.connect(out);

 

            //scrie date in pipe

                  out.write("mesaj scris in pipe");

 

            //citeste din pipe

            while(in.ready()){

                  int x = in.read();

                  System.out.println("Read from pipe:"+(char)x);

            }

           

      }catch(Exception e){

            e.printStackTrace();

      }

}

}//.

Compresia datelor folosind fluxuri

 

În cadrul pachetului java.util.zip sunt definite fluxuri de intrare ieşire ce permit comprimarea şi decomprimarea datelor. Programul următor exemplifică modul în care poate fi comprimat / decomprimat un fişier.

 

package isp.fluxuri.bytes;

 

import java.io.*;

import java.util.zip.*;

 

 

public class ZipUtil {

 

     

      void compressFile(String source, String dest){

          try {

              // Create the GZIP output stream

              String outFilename = dest;

              GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(outFilename));

         

              // Open the input file

              String inFilename = source;

              FileInputStream in = new FileInputStream(inFilename);

         

              // Transfer bytes from the input file to the GZIP output stream

              byte[] buf = new byte[1024];

              int len;

              while ((len = in.read(buf)) > 0) {

                  out.write(buf, 0, len);

              }

              in.close();

           

              // Complete the GZIP file

              out.finish();

              out.close();

          } catch (IOException e) {

            System.out.println("Error compressing file:"+e.getMessage());

          }

      }

     

      void decompressFile(String source, String dest){

             try {

                    // Open the compressed file

                    String inFilename = source;

                    GZIPInputStream in = new GZIPInputStream(new FileInputStream(inFilename));    

                    // Open the output file

                    String outFilename = dest;

                    OutputStream out = new FileOutputStream(outFilename);

               

                    // Transfer bytes from the compressed file to the output file

                    byte[] buf = new byte[1024];

                    int len;

                    while ((len = in.read(buf)) > 0) {

                        out.write(buf, 0, len);

                    }      

                    // Close the file and stream

                    in.close();

                    out.close();

                } catch (IOException e) {

                  System.out.println("Error decompressing file:"+e.getMessage());

                }

      }

     

      void generateFile(String name, long size){

           

            try {

                  FileOutputStream s = new FileOutputStream(new File(name));

                  for(int i=0;i<size;i++){

                        int c = (int)(40+Math.random()*50);

                        s.write(c);

                  }

            } catch (FileNotFoundException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

            } catch (IOException e) {

                  // TODO Auto-generated catch block

                  e.printStackTrace();

            }    

      }

     

      public static void main(String[] args) {

            ZipUtil zu = new ZipUtil();

           

            zu.generateFile("test.txt", 1024);

            zu.compressFile("test.txt", "test.gzip");

            zu.decompressFile("test.gzip","decompressed.txt");   

      }    

     

}