Programmation Java/Entrées Sorties

Un livre de Wikilivres.
Sauter à la navigation Sauter à la recherche


Les opérations d'entrées-sorties concernent la lecture (entrée) et l'écriture (sortie) de données à travers différents types de flux...

En Java, les opérations d'entrées-sorties de base sont gérées par les classes du package java.io. Ces classes obéissent au patron de conception décorateur. Ces objets sont souvent créés au sein d'objets correspondant au patron de conception fabrique.

Flux d'entrée-sortie[modifier | modifier le wikicode]

Le package java.io possède deux classes principales :

  • InputStream : cette classe abstraite définit les fonctions de lecture (entrée ou input en anglais),
  • OutputStream : cette classe abstraite définit les fonctions d'écriture (sortie ou output en anglais).

Ces deux classes abstraites définissent des fonctions bas-niveau et sont implémentées dans différentes sous-classes concrètes. Trois types de flux sont possibles, les flux sur fichiers, les flux sur tubes, et les flux sur zones de mémoire. Par exemple on a :

  • FileInputStream : lecture d'un fichier,
  • FileOutputStream : écriture d'un fichier.

La classe java.net.Socket possèdent des méthodes retournant des instances concrètes des classes InputStream et OutputStream pour lire et écrire depuis/vers la socket TCP.

java.io.InputStream[modifier | modifier le wikicode]

La classe java.io.InputStream possèdent des méthodes lisant une série d'octets (byte).

  • InputStream.read(): lit un byte
  • InputStream.read(byte[] b): lit b.length bytes.
  • InputStream.read(byte[] b, int off, int len): lit len bytes, et les dépose commencer à b[off].

java.io.OutputStream[modifier | modifier le wikicode]

La classe java.io.OutputStream possède des méthodes écrivant une série d'octets (byte).

  • OutputStream.write(): écrit un byte
  • OutputStream.write(byte[] b): écrit b.length bytes.
  • OutputStream.write(byte[] b, int off, int len): écrit len bytes, commencer à b[off].

java.io.PrintStream[modifier | modifier le wikicode]

La classe java.io.PrintStream hérite de la classe java.io.OutputStream, et permet d'afficher tous les types de données sous forme textuelle.

La sortie standard et l'erreur standard impriment sur la console et sont des instances de la classe java.io.PrintStream.

Exemple :

system.out.println("Bonjour !"); // Affiche une chaîne avec retour à la ligne

int count = 100;
system.out.print(count); // Affiche un entier sans retour à la ligne
system.out.print(' ');   // Affiche un caractère

Tout objet peut être affiché car les méthodes print et println appellent la méthode ToString() définie dans la classe java.lang.Object racine de l'arbre hiérarchique de tous les types d'objets.

Exemple :

class NombreComplexe
{
    double n_real, n_img;

    public NombreComplexe(double r, double i)
    {
        this.n_real = r;
        this.n_img = i;
    }

    public String toString()
    {
        return n_real + " + i*"+n_img;
    }
}

NombreComplexe a = new NombreComplexe(1.0, 0.5);
system.out.println(a); // Appelle println(Object) pour afficher :
//                        1.0 + i*0.5

La méthode toString() est également appelée implicitement lors de la concaténation de chaînes de caractères :

String resultat = "Solution complexe :" + a;
// -> Solution complexe : 1.0 + i*0.5

Il est donc important que cette méthode n'ait aucun effet de bord (modification d'un objet, synchronisation, ...).

Lecture-écriture haut niveau[modifier | modifier le wikicode]

Le package java.io possède des classes permettant la lecture et l'écriture de différents types de données.

Reader, Writer, PrintStream, Scanner[modifier | modifier le wikicode]

Pour intéragir avec l'utilisateur dans la console[1].

Exemple concret de flux[modifier | modifier le wikicode]

Dossiers[modifier | modifier le wikicode]

Création[modifier | modifier le wikicode]

Pour créer un dossier :

import java.io.File;

 File mon_dossier = new File("mon_chemin");
 mon_dossier.mkdir();

Pour créer un dossier récursivement (avec ses parents), remplacer mkdir par mkdirs.

Copie[modifier | modifier le wikicode]

Pour copier un dossier (avec son contenu) :

import org.apache.commons.io.FileUtils;

FileUtils.copyDirectory('chemin/source', 'chemin/destination');

Sans la bibliothèque Apache :

public static boolean recursiveCopy(File f_from, File f_to)
{
	// Récupérer les attributs du fichier/répertoire source
	long time = f_from.lastModified();
	boolean cr = f_from.canRead();
	boolean cw = f_from.canWrite();
	boolean cx = f_from.canExecute();

	if (f_from.isDirectory())
	{
		f_to.mkdirs();
		File[] files = f_from.listFiles();
		for(File ff : files)
		{
			File ft = new File(f_to, ff.getName());
			if (!recursiveCopy(ff, ft)) return false;
		}
	}
	else if (f_from.isFile()) // Test permettant d'éviter la copie de certains fichiers spéciaux
	{
		File p = f_to.getParentFile();
		if (!p.exists()) p.mkdirs();
		try
		{
			InputStream in = new FileInputStream(f_from);
			try
			{
				OutputStream out = new FileOutputStream(f_to);
				byte[] b = new byte[8192];
				int len;
				try
				{
					while ((len = in.read(b))>0)
						out.write(b, 0, len);
				}
				finally { out.close(); }
			}
			finally { in.close(); }
		}
		catch (IOException e)
		{ return false; }
	}

	// Mettre les attributs sur le fichier/répertoire destination
	f_to.setReadable(cr);
	f_to.setExecutable(cx);
	f_to.setWritable(cw);
	f_to.setLastModified(time);
	return true;
}

Suppression[modifier | modifier le wikicode]

Pour un répertoire vide, ou un fichier :

import java.io.File;

File mon_chemin = new File("mon_chemin");
mon_chemin.delete();

Pour un répertoire vide ou non, ou un fichier :

import java.io.File;
import org.apache.commons.io.FileUtils;

File mon_dossier = new File("mon_chemin");
FileUtils.deleteQuietly(mon_dossier);

Sans la bibliothèque Apache :

public static boolean recursiveDelete(File f)
{
	if (f.isDirectory())
	{
		File[] files = f.listFiles();
		for(File ff : files)
			if (!recursiveDelete(ff)) return false;
	}
	return f.delete();
}

Fichiers textes[modifier | modifier le wikicode]

Pour lire un fichier texte plusieurs fois en reprenant du début, il faut introduire une variable de type FileChannel, uniquement pour repositionner le lecteur[2] :

import java.io.*;
import java.nio.channels.FileChannel;
    
public class LireDeuxFois {
    public static void main(String[] args) throws Exception {
        if (args.length == 1) {
            FileInputStream fis = new FileInputStream(args[0]);
            FileChannel fc = fis.getChannel();
			int cc;
            // Première lecture
            while ((cc = fis.read()) != -1) {
                System.out.println((char)cc);
            }
			fc.position(0); // Reset
			// Deuxième lecture
            while ((cc = fis.read()) != -1) {
                System.out.println((char)cc);
            }
			fis.close();
        }  
    }
}

Images[modifier | modifier le wikicode]

import javax.imageio.ImageIO;
ImageIO.read(imgage);
ImageIO.write(imgage, "jpg", new File(filename));

Consoles[modifier | modifier le wikicode]

Réseaux[modifier | modifier le wikicode]

Références[modifier | modifier le wikicode]