Blue Flower

Chercher

Création d'un fichier  et écriture dans un fichier en utilisant le flux ( Stream )  I/O

Fichier LogFile.java

Dans l'exemple ci-dessous on ouvre un fichier log si il  existe sinon on le crée. Si le fichier existe on l'ouvre pour écrire dedans .

import static java.nio.file.StandardOpenOption.*;
import java.nio.file.*;
import java.io.*;
public class LogFile {
  public static void main(String[] args) {
    // Convert the string to a
    // byte array.
       String s = "Hello World! ";
        byte data[] = s.getBytes();
        Path p = Paths.get("./logfile.txt");
        try (OutputStream out = new BufferedOutputStream(
           Files.newOutputStream(p, CREATE, APPEND))) {
            out.write(data, 0, data.length);
          } catch (IOException x) {
        System.err.println(x);
    }
 }
}

 Détails et explications

 ......

.......

Fichier LogFilePermission.java

Dans le deuxième  exemple ci-dessous on crée un fichier  avec des permissions spécifiques relatives aux système UNIX et à tou système utilisant le l'API POSIX pour son systeme de fichier. Le code ci-dessou peremtet de créer un fichier applé "logfile.txt " ou d'aller écrire dedans si il existe; si le ficheir est créé on doit le créé ace les d'écriture/lecture  pour le propiétaire  et de lecture seulemen pour le groupe du système.

import static java.nio.file.StandardOpenOption.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;

public class LogFilePermissions {

  public static void main(String[] args) {
  
    // Create the set of options for appending to the file.
    Set options = new HashSet();
    options.add(APPEND);
    options.add(CREATE);

    // Create the custom permissions attribute.
    Set perms =
      PosixFilePermissions.fromString("rw-r-----");
    FileAttribute<Set> attr =
      PosixFilePermissions.asFileAttribute(perms);

    // Convert the string to a ByteBuffer.
    String s = "Hello World! ";
    byte data[] = s.getBytes();
    ByteBuffer bb = ByteBuffer.wrap(data);
    
    Path file = Paths.get("./permissions.log");

    try (SeekableByteChannel sbc =
      Files.newByteChannel(file, options, attr)) {
      sbc.write(bb);
    } catch (IOException x) {
      System.out.println("Exception thrown: " + x);
    }
  }
}

  Détails et explications

Creating and Reading Directories

Some of the methods previously discussed, such as delete, work on files, links and directories. But how do you list all the directories at the top of a file system? How do you list the contents of a directory or create a directory?

  • This section covers the following functionality specific to directories:
  • Listing a File System's Root Directories  
  • Creating a Directory
  • Creating a Temporary Directory
  • Listing a Directory's Contents
  • Filtering a Directory Listing By Using Globbing
  • Writing Your Own Directory Filter
  • Listing a File System's Root Directories
You can list all the root directories for a file system by using the FileSystem.getRootDirectories method. This method returns an Iterable, which enables you to use the enhanced for statement to iterate over all the root directories.
The following code snippet prints the root directories for the default file system:

Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
for (Path name: dirs) {
    System.err.println(name);
}

Creating a Directory

You can create a new directory by using the createDirectory(Path, FileAttribute<?>) method. If you don't specify any FileAttributes, the new directory will have default attributes. For example:

Path dir = ...;
Files.createDirectory(path);

The following code snippet creates a new directory on a POSIX file system that has specific permissions:

Set<PosixFilePermission> perms =
    PosixFilePermissions.fromString("rwxr-x---");
FileAttribute<Set<PosixFilePermission>> attr =
    PosixFilePermissions.asFileAttribute(perms);
Files.createDirectory(file, attr);

To create a directory several levels deep when one or more of the parent directories might not yet exist, you can use the convenience method, createDirectories(Path, FileAttribute<?>). As with the createDirectory(Path, FileAttribute<?>) method, you can specify an optional set of initial file attributes. The following code snippet uses default attributes:

Files.createDirectories(Paths.get("foo/bar/test"));

The directories are created, as needed, from the top down. In the foo/bar/test example, if the foo directory does not exist, it is created. Next, the bar directory is created, if needed, and, finally, the test directory is created.

It is possible for this method to fail after creating some, but not all, of the parent directories.
Creating a Temporary Directory

You can create a temporary directory using one of createTempDirectory methods:

    createTempDirectory(Path, String, FileAttribute<?>...)
    createTempDirectory(String, FileAttribute<?>...)

The first method allows the code to specify a location for the temporary directory and the second method creates a new directory in the default temporary-fle directory

Introduction de WebSocket

WebSocket est un protocole qui permet la communication entre le client et le serveur / endpoint en utilisant une seule connexion TCP. L'avantage de WebSocket par rapport à HTTP est que le protocole est en duplex intégral (permet une communication bidirectionnelle simultanée) et son en-tête est beaucoup plus petit que celui d'un en-tête HTTP, ce qui permet une communication plus efficace même sur de petits paquets de données.

Cycle de vie d'un WebSocket

Le cycle de vie d'un WebSocket est facile à comprendre:

  1. Le client envoie au serveur une demande d'établissement de liaison sous la forme d'un en-tête de mise à niveau HTTP avec des données sur le WebSocket auquel il tente de se connecter.
  2. Le serveur répond à la demande avec un autre en-tête HTTP, c'est la dernière fois qu'un en-tête HTTP est utilisé dans la connexion WebSocket. Si la négociation a réussi, le serveur envoie un en-tête HTTP indiquant au client qu'il passe au protocole WebSocket.
  3. Maintenant, une connexion constante est ouverte et le client et le serveur peuvent s'envoyer n'importe quel nombre de messages jusqu'à ce que la connexion soit fermée. Ces messages ont seulement environ 2 octets de surcharge.

L'API WebSocket a été introduite avec Java EE7, dans cet exemple, nous allons créer un client qui enverra un message au serveur et le serveur le renverra.

Exemple

 Server Endpoint

Le point de terminaison du serveur gérera les messages WebSocket entrants; il s’agit d’un objet Java (POJO) qui utilise les annotations de Java pour définir ses méthodes (cela peut être fait par programmation mais semble beaucoup plus propre en utilisant l’annotation).

Voici le code du "endpoint" du serveur:

import java.io.IOException ;

import javax.websocket.OnClose ;
import javax.websocket.OnMessage ;
import javax.websocket.OnOpen ;
import javax.websocket.Session ;
import javax.websocket.server.ServerEndpoint ;

/ **
* @ServerEndpoint donne le nom relatif du point final
* Ceci sera accessible via ws: // localhost: 8080 / EchoChamber / echo
* Où "localhost" est l'adresse de l'hôte,
* "EchoChamber" est le nom du package
* et "echo" est l'adresse pour accéder à cette classe depuis le serveur
* /
@ServerEndpoint ( "/ echo" )
classe publique EchoServer { / **

* @OnOpen nous permet d'intercepter la création d'une nouvelle session.
* La classe de session nous permet d'envoyer des données à l'utilisateur.
* Dans la méthode onOpen, nous ferons savoir à l'utilisateur que la poignée de main a été
* à succès.
* /
@OnOpen
public void onOpen ( Session session ) {
System.out.println ( session.getId ( ) + "a ouvert une connexion" ) ;
essayez {
session. getBasicRemote ( ).sendText ( "Connexion établie" ) ;
} catch ( IOException ex ) {
ex. printStackTrace ( ) ;
}
}

/ **
* Lorsqu'un utilisateur envoie un message au serveur, cette méthode intercepte le message
* et laissez-nous y réagir. Pour l'instant, le message est lu comme une chaîne.
* /
@OnMessage
public void onMessage ( String message, Session session ) {
System.out.println ( "Message de" + session.getId ( ) + ":" + message ) ;
essayez {
session. getBasicRemote ( ).sendText ( message ) ;
} catch ( IOException ex ) {
ex. printStackTrace () ;
}
}

/ **
* L'utilisateur ferme la connexion.
*
* Remarque: vous ne pouvez pas envoyer de messages au client à partir de cette méthode
* /
@OnClose
public void onClose ( Session session ) {
System.out.println ( "Session" + session.getId ( ) + "s'est terminée" ) ;
}
}

... 

à suivre ....

Qu'est ce qu' un Path ?

La plupart des systèmes de fichiers actuellement utilisés stockent les fichiers dans une structure arborescente (ou hiérarchique). Au sommet de l'arborescence se trouve un (ou plusieurs) nœud racine. Sous le nœud racine, il y a des fichiers et des répertoires (dossiers dans Microsoft Windows). Chaque répertoire peut contenir des fichiers et des sous-répertoires, qui peuvent à leur tour contenir des fichiers et des sous-répertoires, etc., potentiellement à une profondeur presque illimitée.

Un fichier est identifié par son chemin d'accès dans le système de fichiers, en partant du nœud racine;

Les Fichiers Java

La classe File définie comme suit:

"public class File extends Object implements Serializable, Comparable<File>" 

est une classe abstraite qui représente à la fois les fichiers et les répertoires

Cette  classe File n'est pas utilisée pour lire ou écrire des données (pour cela il existe d'autres classes java) ; elle  est utilisée pour la création de nouveaux fichiers vides, pour faire des recherches dans des fichiers , pour supprimer des fichiers ( elle sert aussi pour les mêmes actions dan les  répertoires - créer , ...) .
Prenons l'exemple suivant :
File file = new File("monFile.txt");

Après cette ligne de code on a créé juste un objet "file" de type File  mais on a aucun fichier physique dans mon répertoire de travail; pour créer effectivement le fichier physique on utilise la méthode "File.createNewFile() de type booléen comme suit:

Boolean leFichierEstcree = file.createNewFile();

Cette méthode crée le fichier physique "monFile.txt"  s'il n'existe pas sur le disque  (dans ce cas elle retourne false i.e que le fichier en question n'existe pas sur le disque  par conséquent  il va être créé ) si le fichier "monFile.txt" existe déjà sur le disque et la méthode retourne "true" ( le fichier en question existe sur le disque et il n'est pas à créé) .

Les flux

Le package java.io fournit une bibliothèque complète de classes permettant de traiter les entrées et les sorties. Java fournit le flux en tant que mécanisme général pour les E / S de données
Stream implémente un accès séquentiel aux données. Il existe deux types de flux: les flux d'octets (flux binaires) et les flux de caractères (flux de texte).

.................

An input stream is an object that an application can use to read a sequence of data, and an output stream is an object that an application can use to write a sequence of data. An input stream  acts as a source of data, and an output acts as a destination of data.

.................. 

  • FileReader
    This class is used to read character files. Its read() methods are fairly low-level, allowing us to read single characters, the whole stream of characters, or a fixed number of characters. FileReaders are usually wrapped by higher-level objects such as BufferedReaders, which improve performance and provide more convenient ways to work with data.
  • BufferedReader
    This class is used to make lower-level Reader classes like FileReader more efficient and easier to use. Compared to FileReaders, BufferedReaders read relatively large chunks of data from a file at once, and keep this data in a buffer. When you ask for the next character or line of data, it is retrieved from the buffer, which minimizes the number of times that time-intensive, file read operations are performed. In addition, BufferedReader provides more convenient methods such as readLine(), that allow us to get the next line of characters from a file.
  • BufferedWriter
    This class is used to make lower-level classes like FileWriters more efficient and easier to use. Compared to FileWriters, BufferedWriters write relatively large chunks of data to a file at once, minimizing the number of times that slow, file writing operations are performed. The BufferedWriter class also provides a newLine() method to create platform-specific line separators automatically.
  • PrintWriter
    This class has been enhanced significantly in Java 5. Because of newly created methods and constructors (like building a PrintWriter with a File or a String), we might find that we can use PrintWrite in places where we previously needed a Writer to be wrapped with a FileWriter and/or a BufferedWriter. New methods like format(), printf(). and append() make PrintWriters very flexible and powerful.
  • Console
    This new, Java 6 convenience class provides methods to read input from the console and write formatted output to the console

....................

Les flux (streams en anglais) permettent d'encapsuler les processus permettant d'envoyer  et de recevoir des données en Java. Le traitement des flux de données se font de façon séquentielle. En jav les flus de données sont vues soit sous forme de:

  • de flux d'entrée (input stream) et de flux de sortie (output stream)
  • de flux de traitement de caractères et de flux de traitement d'octets

En Java  les flux servent pour lire ou écrire des données. En java  on dispose aussi  de classes pour  faire des traitements sur les données du flux. Ces classes sont spécialisées soit à  lecture soit à l'écriture.

Toutes ces classes sont regroupées dans le package java.io.

...

La communication par socket en Java

L'interface socket BSD, l'interface de programmation réseau la plus courante, permet la communication par socket selon le schéma habituel client-serveur. Dans java l'interface des sockets qui se trouve dans le package "java.net" permet un accès simple aux sockets sur IP.

Les classes

Pour réaliser une communication par socket en java on se sert, de la classe "java.net.InetAddress" pour manipuler des adresses IP, de la classe "java.net.SocketServer" côté serveur si on travaille en mode connecté. La classe "java.net.Socket" permet de programmer l'interface côté client et la communication effective par flot via les sockets. Les classes java.net.DatagramSocket et java.net.DatagramPacket servent à programmer la communication en mode datagramme.

1. La classe java.net.InetAddress

Cette classe représente les adresses IP et un ensemble de méthodes pour les manipuler. Elle encapsule aussi l'accès au serveur de noms DNS et elle a comme signature:

   public class InetAddress implements Serializable

1.1 Les opérations de la classe InetAddress

Conversion de nom vers adresse IP :

Un premier ensemble de méthodes permet de créer des objets adresses IP.

   public static InetAddress getLocalHost() throws UnknownHostException

Cette méthode renvoie l'adresse IP du site local d'appel.

    public static InetAddress getByName(String host) throws UnknownHostException

Cette méthode construit un nouvel objet InetAddress à partir d'un nom textuel de site. Le nom du site est donné sous forme symbolique (ocamil.com) ou sous forme numérique (147.120.17.03).

Enfin,

   public static InetAddress[] getAllByName(String host) throws UnknownHostException

permet d'obtenir les différentes adresses IP d'un site.

Conversions inverses

Des méthodes applicables à un objet de la classe InetAddress permettent d'obtenir dans divers formats des adresses IP ou des noms de site. Les principales sont :

public String getHostName() obtient le nom complet correspondant à l'adresse IP
public String getHostAddress() obtient l'adresse IP sous forme %d.%d.%d.%d
public byte[] getAddress() obtient l'adresse IP sous forme d'un tableau d'octets.

1.2 La classe ServerSocket

Cette classe implante un objet ayant un comportement de serveur via une interface par socket.

   public class java.net.ServerSocket

Une implantation standard du service existe mais peut être redéfinie en donnant une implantation explicite sous la forme d'un objet de la classe java.net.SocketImpl. Nous nous contenterons d'utiliser la version standard.

1.2.1 Le constructeur ServerSocket

   public ServerSocket(int port) throws IOException
    public ServerSocket(int port, int backlog) throws IOException
    public ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException

Ces constructeurs créent un objet serveur à l'écoute du port spécifié. La taille de la file d'attente des demandes de connexion peut être explicitement spécifiée via le paramètre backlog. Si la machine possède plusieurs adresses, on peut aussi restreindre l'adresse sur laquelle on accepte les connexions.

Appels système :

ce constructeur correspond à l'utilisation des primitives socket, bind et listen.

1.2.2 Les opérations de la classe ServerSocket

Nous ne retiendrons que les méthodes de base. La méthode essentielle est l'acceptation d'une connexion d'un client :

    public Socket accept() throws IOException

Cette méthode est bloquante, mais l'attente peut être limitée dans le temps par l'appel préalable de la méthode setSoTimeout. Cette méthode prend en paramètre le délai de garde exprimé en millisecondes. La valeur par défaut 0 équivaut à l'infini. À l'expiration du délai de garde, l'exception java.io.InterruptedIOException est levée.

    public void setSoTimeout(int timeout) throws SocketException

La fermeture du socket d'écoute s'exécute par l'appel de la méthode close.

Enfin, les méthodes suivantes retrouvent l'adresse IP ou le port d'un socket d'écoute :

   public InetAddress getInetAddress() 
    public int getLocalPort()

1.3 La classe java.net.Socket

La classe java.net.Socket est utilisée pour la programmation des sockets connectés, côté client et côté serveur.

   public class java.net.Socket

Comme pour le serveur, nous utiliserons l'implantation standard bien qu'elle soit redéfinissable par le développement d'une nouvelle implantation de la classe java.net.SocketImpl.

1.3.1 Constructeurs

Côté serveur, la méthode accept de la classe java.net.ServerSocket renvoie un socket de service connecté au client. Côté client, on utilise :

public Socket(String host, int port) throws UnknownHostException, IOException
    public Socket(InetAddress address, int port) throws IOException
    public Socket(String host, int port, InetAddress localAddr, int localPort)
                throws UnknownHostException, IOException
    public Socket(InetAddress addr, int port, InetAddress localAddr, int localPort)
                throws IOException

Les deux premiers constructeurs construisent un socket connecté à la machine et au port spécifiés. Par défaut, la connexion est de type TCP fiable. Les deux autres interfaces permettent en outre de fixer l'adresse IP et le numéro de port utilisés côté client (plutôt que d'utiliser un port disponible quelconque).

Appels système :

ces constructeurs correspondent à l'utilisation des primitives socket, bind (éventuellement) et connect.

1.3.2 Opérations de la classe Socket

La communication effective sur une connexion par socket utilise la notion de flots de données (java.io.OutputStream et java.io.InputStream). Les deux méthodes suivantes sont utilisés pour obtenir les flots en entrée et en sortie.

 public InputStream  getInputStream()  throws IOException
    public OutputStream getOutputStream() throws IOException

Les flots obtenus servent de base à la construction d'objets de classes plus abstraites telles que java.io.DataOutputStream et java.io.DataInputStream (pour le JDK1), ou java.io.PrintWriter et java.io.BufferedReader (JDK2 et +).

Une opération de lecture sur ces flots est bloquante tant que des données ne sont pas disponibles. Cependant, il est possible de fixer un délai de garde à l'attente de données (similaire au délai de garde du socket d'écoute : levée de l'exception java.io.InterruptedIOException) :

 public void setSoTimeout(int timeout) throws SocketException

Un ensemble de méthodes permet d'obtenir les éléments constitutifs de la liaison établie :

public InetAddress getInetAddress() fournit l'adresse IP distante
public InetAddress getLocalAddress() fournit l'adresse IP locale
public int getPort() fournit le port distant
public int getLocalPort() fournit le port local


L'opération close ferme la connexion et libère les ressources du système associées au socket.

1.4 Socket en mode datagramme DatagramSocket

La classe java.net.DatagramSocket permet d'envoyer et de recevoir des paquets (datagrammes UDP). Il s'agit donc de messages non fiables (possibilités de pertes et de duplication), non ordonnés (les messages peuvent être reçus dans un ordre différent de celui d'émission) et dont la taille (assez faible -- souvent 4Ko) dépend du réseau sous-jacent.

 public class java.net.DatagramSocket

1.4.1 Constructeurs

public DatagramSocket() throws SocketException
    public DatagramSocket(int port) throws SocketException

Construit un socket datagramme en spécifiant éventuellement un port sur la machine locale (par défaut, un port disponible quelconque est choisi).

1.4.2 Émission/réception

public void send(DatagramPacket p) throws IOException
public void receive(DatagramPacket p) throws IOException

Ces opérations permettent d'envoyer et de recevoir un paquet. Un paquet est un objet de la classe java.net.DatagramPacket qui possède une zone de données et (éventuellement) une adresse IP et un numéro de port (destinataire dans le cas send, émetteur dans le cas receive). Les principales méthodes sont :

 public DatagramPacket(byte[] buf, int length)
    public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    public InetAddress getAddress()
    public int getPort()
    public byte[] getData()
    public int getLength()
    public void setAddress(InetAddress iaddr)
    public void setPort(int iport)
    public void setData(byte[] buf)
    public void setLength(int length)

Les constructeurs renvoient un objet pour recevoir ou émettre des paquets. Les accesseurs get* permettent, dans le cas d'un receive, d'obtenir l'émetteur et le contenu du message. Les méthodes de modification set* permettent de changer les paramètres ou le contenu d'un message pour l'émission.

1.4.3 Connexion

Il est possible de « connecter » un socket datagramme à un destinataire. Dans ce cas, les paquets émis sur le socket seront toujours pour l'adresse spécifiée. La connexion simplifie l'envoi d'une série de paquets (il n'est plus nécessaire de spécifier l'adresse de destination pour chacun d'entre eux) et accélère les contrôles de sécurité (ils ont lieu une fois pour toute à la connexion). La « déconnexion » enlève l'association (le socket redevient disponible comme dans l'état initial).

 public void connect(InetAddress address, int port)
    public void disconnect()

1.4.4 Divers

Diverses méthodes renvoient le numéro de port local et l'adresse de la machine locale (getLocalPort et getLocalAddress), et dans le cas d'un socket connecté, le numéro de port distant et l'adresse distante (getPort et getInetAddress). Comme précédemment, on peut spécifier un délai de garde pour l'opération receive avec setSoTimeout. On peut aussi obtenir ou réduire la taille maximale d'un paquet avec getSendBufferSize, getReceiveBufferSize, setSendBufferSize et setReceiveBufferSize.
Enfin, n'oublions pas la méthode close qui libère les ressources du système associées au socket.