Sunteți pe pagina 1din 11

Laborator Programare Java Lucrarea nr.

LUCRAREA NR. 8
Stream-uri de intrare-ieșire. Clasa File. Serializare.

1. Scopul lucrării

Această lucrare de laborator prezintă operațiile de intrare-ieșire în Java pe baza unor exemple,
precum și mecanismul de serializare a obiectelor.

2. Stream-uri standard
Limbajul Java pune la dispoziția utilizatorului trei stream-uri standard, din pachetul java.io:
➢ stream-ul standard de intrare
➢ stream-ul standard de ieșire
➢ stream-ul standard de erori
Stream-ul standard de intrare este utilizat pentru preluarea datelor, iar celelalte două stream-uri
standard sunt utilizate pentru afișarea datelor și a mesajelor de eroare. Implicit stream-ul de intrare
preia datele de la tastatură iar celelalte două afișează datele la monitor.
Stream-urile standard sunt definite în clasa System, prin variabilele System.in, System.out,
System.err.
Programul următor afișează o listă cu opțiuni corespunzătoare mai multor tipuri de informații
disponibile spre afișare. Utilizatorul poate alege una din opțiuni prin tastarea unei litere. Se va afișa
informația cerută de utilizator.

import java.io.*;
import java.util.*;

public class IOStandard {


public static void main(String args [ ]) {
boolean exit = false;
System.out.println("Vom vedea cateva informatii despre sistem");
while(!exit) {
System.out.println(" Ce doresti sa vezi?:");
System.out.println("\t (d) Data ");
System.out.println("\t (p) Proprietati ");
System.out.println("\t (x) Iesire ");
try {
char readChar = (char) (System.in.read( ) );

1
Laborator Programare Java Lucrarea nr. 8

int av = System.in.available();
System.in.skip(av);
switch(readChar) {
case 'd' : case 'D':
System.out.println("Data:" + new Date().toString());
break;
case 'p' : case 'P':
Properties prop = System.getProperties();
prop.list(System.out);
break;
case 'x' : case 'X':
System.out.println("La revedere!");
exit = true;
break;

}
}
catch(IOException e) {
System.err.println(e.getMessage());
}
}
}

}
Observații. În program s-a folosit o variabilă booleană exit ca flag de ieșire din program, dar se putea
utilize metoda System.exit(0) pentru acest lucru.Citirea folosind metoda read( ) se încheie doar în
momentul apăsării tastei Enter. În cazul în care se introduce mai multe caractere se citește doar
primul dintre ele, se calculează numărul de caractere rămase necitite (cu metoda available() ) și se
sare peste ele (cu metoda skip() ). Toate operațiile se execută în interiorul unui bloc try-catch datorită
excepțiilor de tip IOException ce pot fi aruncate de metodele apelate prin System.in.
Metoda getProperties
- Este o metodă a clasei System și returnează un obiect de tip Properties, care este o clasă
derivată din clasa Hashtable.
- Are prototipul:
public static Properties getProperties( )
- Determină proprietățile sistemului current
- Mulțimea proprietăților include valorile asociate cheilor, semnificația este dată mai jos (din
documentația API Java):

2
Laborator Programare Java Lucrarea nr. 8

Întrebare: Ce face metoda getMessage( ) ?

3
Laborator Programare Java Lucrarea nr. 8

3. Utilizarea claselor Reader și InputStreamReader


Următorul program prezintă o aplicație de criptare/decriptare a unui text dat în linia de comandă.
Criptarea se face folosind algoritmul lui Caesar cu cheie simetrică, cheia k având valoare cuprinsă
între 0 și 25) și trebuie să fie aceeași la criptare și la decriptare.

// Caesar.java: implement the Caesar cipher


// This carries out a simple rotation of lower-case letters,
// and does nothing to all other characters, making the decryption
// process even easier, because caps and punctuation marks survive unchanged.
// Usage: java Caesar (-d | -e) key
// Above, option "-d" is for decryption, while "-e" is for encryption
import java.io.*;
public class Caesar {
private Reader in; // standard input stream for message
private int key; // (en|de)cryption key

// Caesar: constructor, opens standard input, passes key


public Caesar(int k) {
// open file
in = new InputStreamReader(System.in);
key = k;
}
// (en|de)crypt: just feed in opposite parameters
public void encrypt() { translate(key); }
public void decrypt() { translate(-key); }

// translate: input message, translate


private void translate(int k) {
char c;
while ((byte)(c = getNextChar()) != -1) {
if (Character.isLowerCase(c)) {
c = rotate(c, k);
}
System.out.print(c);
}
}

// getNextChar: fetches next char.


public char getNextChar() {
char ch = ' '; // = ' ' to keep compiler happy
try {
ch = (char)in.read();
} catch (IOException e) {
System.out.println("Exception reading character");
}
return ch;
}
// rotate: translate using rotation, version with table lookup
public char rotate(char c, int key) { // c must be lowercase
String s = "abcdefghijklmnopqrstuvwxyz";

4
Laborator Programare Java Lucrarea nr. 8

int i = 0;
while (i < 26) {
// extra +26 below because key might be negative
if (c == s.charAt(i)) return s.charAt((i + key + 26)%26);
i++;
}
return c;
}

// main: check command, (en|de)crypt, feed in key value


public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: java Caesar (-d | -e) key");
System.exit(1);
}
Caesar cipher = new Caesar(Integer.parseInt(args[1]));
if (args[0].equals("-e")) cipher.encrypt();
else if (args[0].equals("-d")) cipher.decrypt();
else {
System.out.println("Usage: java Caesar (-d | -e) key");
System.exit(1);
}
}
}

Creați un proiect și executați aplicația Caesar folosind o comandă de forma java Caesar –e 3, în linia
de comandă.
Pentru detalii privind algoritmi de criptare în limbajul Java se poate studia cartea „The laws of
Cryptography with Java Code” al lui Neal R. Wagner.

4. Clasa File
Exemplul 1. Listarea conținutului unui director

/* Programul listeaza fisierele si subdirectoarele unui director. Pentru fiecare


din ele vor fi afisate diverse informatii. Numele directorului este primit ca
argument de la linia de comanda, sau este directorul curent.
*/
import java .io .*;
import java . util .*;
public class ListareDirector {
private static void info ( File f) {
// Afiseaza informatii despre un fisier sau director
String nume = f. getName ();
if(f. isFile ())
System . out. println (" Fisier : " + nume );
else
if(f. isDirectory ())

5
Laborator Programare Java Lucrarea nr. 8

System . out. println (" Director : " + nume );


System . out. println (
" Cale absoluta : " + f. getAbsolutePath () +
"\n Poate citi : " + f. canRead () +
"\n Poate scrie : " + f. canWrite () +
"\n Parinte : " + f. getParent () +
"\n Cale : " + f. getPath () +
"\n Lungime : " + f. length () +
"\n Data ultimei modificari : " +
new Date (f. lastModified ()));
System . out. println (" --------------");
}
public static void main ( String [] args ) {
String nume ;
if ( args . length == 0)
nume = "."; // directorul curent
else
nume = args [0];
try {
File director = new File ( nume );
File [] continut = director. listFiles ();
for (int i = 0; i < continut . length ; i ++)
info ( continut [i]);
} catch ( Exception e) {
e. printStackTrace ();
}
}
}
Exemplul 2. Următorul program copie conținutul a două fișiere într-un alt fișier specificat.
import java.io.*;

public class CopyMultipleFiles{

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


BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Introduceti numarul de fisiere ce se doresc a fi
copiate");
int n = Integer.parseInt(bf.readLine());
String fileName[] = new String[n];

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


System.out.println("Introduceti numele fisierului:");
fileName[i] = bf.readLine();
}

for (int j=0; j<n-1; j++){


copyfile(fileName[j],fileName[j+1]);
}
System.out.println("Fisierul a fost copiat.");
}

public static void copyfile(String srFile, String dtFile){

6
Laborator Programare Java Lucrarea nr. 8

try{
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
//pentru adaugarea in fisier
OutputStream out = new FileOutputStream(f2,true);

//pentru suprascrierea fisierului.


//OutputStream out = new FileOutputStream(f2);

byte[] buf = new byte[1024];


int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
}
catch(FileNotFoundException ex){
System.out.println(ex.getMessage() + " in directorul specificat.");
System.exit(0);
}
catch(IOException e){
System.out.println(e.getMessage());
}
}
}

5. Serializarea obiectelor

Serializarea reprezintă un mecanism prin care un obiect poate fi transformat într-o secvență de bytes
care poate fi folosită pentru refacerea completă a obiectului inițial. Secvența de bytes poate fi
transmisă în rețea sau poate fi stocată într-o memorie.
Avantajul serializării este faptul că simplifică procedura de transmitere a unui obiect între două entități
ale unui sistem. Reconstituirea unui obiect din forma serializată se poate face , fie pe aceeași mașină,
fie pe o altă platformă decât cea pe care s-a creat serializarea.
Pentru a fi serializabilă, o clasă trebuie să implementeze interfața Serializable din pachetul java.io.
Dacă se dorește ca o variabilă de instanță să fie ignorată în procesul de serializare, se marchează
variabila respectivă ca tranzitorie, folosind cuvântul cheie transient.
Deserializarea reprezintă procedura de refacere completă a obiectului inițial.
Aplicația următoare are ca scop salvarea și refacerea stării personajelor unui joc.

7
Laborator Programare Java Lucrarea nr. 8

Clasa GameCharacter
import java.io.Serializable;

public class GameCharacter implements Serializable


{
int power;
String type;
String[] weapons;

public GameCharacter(int p, String t, String[] w)


{
power = p;
type = t;
weapons = w;
}

public int getPower() {


return power;
}

public String getType() {


return type;
}

public String getWeapons() {


String weaponList = "";
for (int i = 0; i < weapons.length; i++)
{
weaponList += weapons[i] + " ";
}
return weaponList;
}
}
Clasa GameSaverTest

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
public class GameSaverTest
{
public static void main (String[] args) {
GameCharacter one = new GameCharacter(50, "Elf", new String[] {"bow",
"sword", "dust"});
GameCharacter two = new GameCharacter(200, "Troll", new String[] {"bare
hands", "big axe"});
GameCharacter three = new GameCharacter(120, "Magician", new String[]
{"spells", "invisibility"});

8
Laborator Programare Java Lucrarea nr. 8

//imagineaza-ti aici cod care face diferite lucruri cu personajele


// din joc si le poate modifica valorile de stare

try {
ObjectOutputStream os = new ObjectOutputStream(new
FileOutputStream("Game.ser"));
os.writeObject(one);
os. writeObject (two);
os. writeObject (three);
os.close();
}
catch (IOException ex) {
ex.printStackTrace();
}

one = null;
two = null;
three = null;

try {
ObjectInputStream is = new ObjectInputStream(new
FileInputStream("Game.ser"));
GameCharacter oneRestore = (GameCharacter) is.readObject();
GameCharacter twoRestore = (GameCharacter) is.readObject();
GameCharacter threeRestore = (GameCharacter) is.readObject();

System.out.println("One's type: " + oneRestore.getType());


System.out.println("Two's type: " + twoRestore.getType());
System.out.println("Three's type: " + threeRestore.getType());
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}

Observație. Verificați crearea fișierului Game.ser în directorul current. Datele din fișier par a nu avea
sens dacă le citim ca text. Un fișier serializat este mai greu de citi de către noi, dar este mai ușor și
mai sigur pentru un program să refacă starea obiectelor din informațiile serializate decât prin citirea
valorilor variabilelor salvate într-un fișier text.
Întrebare: Ce face metoda getType( ) ?

9
Laborator Programare Java Lucrarea nr. 8

6. Verificarea cunoștințelor
1) Rearanjați secvențele de cod astfel încât să obțineți un program Java funcțional care produce
rezultatele de mai jos?
% java DungeonTest
12
8

10
Laborator Programare Java Lucrarea nr. 8

2) Răspundeți la următoare întrebări prin adevărat sau fals:


1. Starea obiectelor poate fi salvată numai prin serializare.
2. ObjectOutputStream este o clasă folosită pentru salvarea obiectelor serializate.
3. Un singur apel al metodei writeObject( ) poate salva mai multe obiecte.
4. Toate clasele sunt serializabile în mod prestabilit.
5. Modificatorul transient îți permite să faci variabilele de instanță serializabile.
6. Dacă o superclasă nu este serializabilă, atunci nici subclasele nu sunt serializabile.
7. Atnci când un obiect este deserializat, constructorul clasei nu este executat.
8. Obiectele File reprezintă fișiere, dar nu și directoare.
9. Atât serializarea, cât și salvarea într-un fișier de text pot lansa excepții.

7. Temă pentru acasă

1. Creați o clasă care să copie un director sau un fișier dintr-un director în altul.
2. Descrieți pe scurt clasa RandomAccesFile

11

S-ar putea să vă placă și