Nio : Charset, Channel

La classe Charset permet d'encoder et de décoder les caractères de JAVA dans divers encodages.
Le concept de canal Channel a été introduit pour la première fois dans le package nio : il permet un meilleur contrôle des fluxs de fichier, de socket, de datagramme et de pipe.
Enfin, le socket de serveur, qui ne faisait qu'attendre des demandes de connexions pour créer un véritable socket "privé" de connection entre un client et le serveur, devient un ServerSocketChannel. Le Socket d'échange "privé" entre client et serveur devient un SocketChannel.

Buffer et Channel

Source de BufferNio5.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class BufferNio5
{
  static public void main(String args[]) throws Exception {
    FileInputStream fin = new FileInputStream("alphabet.txt");
    FileChannel canal = fin.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate(10);
    canal.read(buffer);
    buffer.flip();
    affiche(buffer);
    buffer.clear();
    canal.read(buffer);
    buffer.flip();
    affiche(buffer);
    buffer.clear();
    canal.read(buffer);
    buffer.flip();
    affiche(buffer);
    fin.close();
  } 
  static public void affiche(ByteBuffer buffer) {
    int i=0;
    while (buffer.remaining()>0) 
      System.out.print((char)buffer.get());
    System.out.println();
  }
}

EXECUTION
$java BufferNio5
abcdefghij
klmnopqrst
uvwxyz

Les lignes de la classe :

Source de BufferNio6.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class BufferNio6
{
  static public void main(String args[]) throws Exception {
    FileInputStream fin = new FileInputStream("alphabet.txt");
    FileChannel canal = fin.getChannel();
    ByteBuffer buffer = ByteBuffer.allocate( 10 );
    canal.read( buffer );
    buffer.flip();
    affiche(buffer);
    canal.read( buffer );
    buffer.flip();
    affiche(buffer);
    fin.close();
  }  
  static public void affiche(ByteBuffer buffer) {
    int i=0;
    while (buffer.remaining()>0) 
      System.out.print( (char)buffer.get() );
    System.out.println();
  }
}

EXECUTION
$java BufferNio6
abcdefghij
abcdefghij // inchangé

Les lignes de la classe :

copie de fichier avec Buffer et Channel

Source de CopyFile.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
public class CopyFile
{
  static public void main(String args[]) throws Exception {
    if (args.length<2) {
      System.err.println("Usage: java CopyFile source destination");
      System.exit(1);
    } else {
      FileInputStream fIn = new FileInputStream(args[0]);
      FileOutputStream fOut = new FileOutputStream(args[1]);
      FileChannel canalIn = fIn.getChannel();
      FileChannel canalOut = fOut.getChannel();
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      int nombreLu = 0;
      while (nombreLu != -1) {
        buffer.clear();
        nombreLu = canalIn.read(buffer);
        if (nombreLu !=-1) {
          buffer.flip();
          canalOut.write(buffer);
        }
      }
      canalIn.close();
      canalOut.close();
      fIn.close();
      fOut.close();
    }
  }
}

EXECUTION
$ cat alphabet
abcdefghijklmnopqrstuvwxyz
$java CopyFile alphabet.txt alpha2
$ cat alpha2
abcdefghijklmnopqrstuvwxyz

Les lignes de la classe :

Charset : encodage et décodage

Source de Charset1.java
import java.io.*;
import java.nio.*;
import java.nio.charset.*;
public class Charset1
{
  static public void main( String args[] ) throws Exception {
    CharBuffer carBuf = CharBuffer.wrap("abcd\u00E9");
    System.out.println("CharBuffer = "+carBuf );
    Charset charset = Charset.forName("ISO-8859-1");
    System.out.println("Charset ISO-8859-1");
    ByteBuffer byteBuf = charset.encode(carBuf);
    System.out.println("ByteBuffer charset.encode(carBuf) : ");
    while (byteBuf.remaining()>0) 
      System.out.print(UnicodeFormatter.byteToHex(byteBuf.get())
                       + " " );
    System.out.println();
    byteBuf.flip();
    CharBuffer carBuf2 = charset.decode(byteBuf);
    System.out.println("CharBuffer charset.decode(byteBuf) : "
                       +carBuf2 );   
    
    charset = Charset.forName("UTF-8");
    System.out.println("Charset UTF-8");
    carBuf.flip();
    byteBuf = charset.encode(carBuf);
    System.out.println("ByteBuffer charset.encode(carBuf) : ");
    while (byteBuf.remaining()>0) {
      System.out.print( UnicodeFormatter.byteToHex(byteBuf.get()) + " " );
    }
    System.out.println();
    byteBuf.flip();
    carBuf2 = charset.decode(byteBuf);
    System.out.println("CharBuffer charset.decode(byteBuf) : "+carBuf2 );      
   }
}

EXECUTION
$java Charset1
CharBuffer = abcdÚ
Charset ISO-8859-1
ByteBuffer charset.encode(carBuf) :
61 62 63 64 e9
CharBuffer charset.decode(byteBuf) : abcdÚ
Charset UTF-8
ByteBuffer charset.encode(carBuf) :
61 62 63 64 c3 a9
CharBuffer charset.decode(byteBuf) : abcdÚ

Les lignes de la classe :

Source de UnicodeFormatter.java fourni par SUN
public class UnicodeFormatter  {
   static public String byteToHex(byte b) {
      // Returns hex String representation of byte b
      char hexDigit[] = {
         '0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
      };
      char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
      return new String(array);
   }
   static public String charToHex(char c) {
      // Returns hex String representation of char c
      byte hi = (byte) (c >>> 8);
      byte lo = (byte) (c & 0xff);
      return byteToHex(hi) + byteToHex(lo);
   }
}

Charset et Channel

Source de BufferCharset1.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;

public class BufferCharset1
{
  static public void main( String args[] ) throws Exception {
    FileInputStream fin = new FileInputStream("alphabet.txt");
    Charset charset = Charset.forName("ISO-8859-1");
    CharsetDecoder decoder = charset.newDecoder();
    FileChannel canal = fin.getChannel();
    ByteBuffer byteBuf = ByteBuffer.allocate( 10 );
    canal.read(byteBuf);
    byteBuf.flip();
    CharBuffer carBuf = decoder.decode(byteBuf);
    System.out.println("lu : "+carBuf.toString());
    byteBuf.clear();
    canal.read(byteBuf);
    byteBuf.flip();
    carBuf = decoder.decode(byteBuf);
    System.out.println("lu : "+carBuf.toString());
    byteBuf.clear();
    canal.read(byteBuf);
    byteBuf.flip();
    carBuf = decoder.decode(byteBuf);
    System.out.println("lu : "+carBuf.toString());
    fin.close();
  }
}

EXECUTION
$java BufferCharset1
lu : abcdefghij
lu : klmnopqrst
lu : uvwxyz

Les lignes de la classe :

SocketChannel

Source de GetDayTime.java
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.net.*;
class GetDayTime {
  public static void main(String args[]) throws Exception {
    if (args.length != 2)
      System.out.println("usage : java GetDayTime hote port");
    else {
      String hote = args[0];
      int port = Integer.parseInt(args[1]);
      InetSocketAddress hoteAdress = new InetSocketAddress(hote,port);
      SocketChannel socket = SocketChannel.open(hoteAdress);
      Charset charset = Charset.forName("US-ASCII");
      CharsetDecoder decoder = charset.newDecoder();
      ByteBuffer byteBuf = ByteBuffer.allocate(10);
      while (socket.read(byteBuf) != -1) {
        byteBuf.flip();
        decoder.reset();
        CharBuffer charBuf = decoder.decode(byteBuf);
        System.out.print(charBuf.toString());
        byteBuf.clear();
      }
      System.out.println();
      socket.close();
    }
  }
}

EXECUTION
Récupérer et compiler SSCdayTime.java

sur une console lancer le serveur :
$java SSCdayTime 4444

sur une autre console :
$java GetDayTime localhost 4444
Wed Jan 11 18:26:09 CET 2006

Les lignes de la classe :

ServerSocketChannel

Source de SSCdayTime.java
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.net.*;
import java.util.*;
class SSCdayTime {
  public static void main(String args[]) throws Exception {
    if (args.length != 1)
      System.out.println("usage : java SSCdayTime port");
    else {
      int port = Integer.parseInt(args[0]);
      InetSocketAddress inetAdress = new InetSocketAddress(port);
      ServerSocketChannel serverChannel = ServerSocketChannel.open();
      ServerSocket serverSocket = serverChannel.socket();
      serverSocket.bind(inetAdress);
      Charset charset = Charset.forName("US-ASCII");
      CharsetEncoder encoder = charset.newEncoder();
      while (true) {
        SocketChannel sockClient = serverChannel.accept(); 
        Date maintenant = new Date();
        CharBuffer reponse = CharBuffer.wrap(maintenant);
        encoder.reset();
        sockClient.write(encoder.encode(reponse));
        sockClient.close();
      }
    }
  }
}

EXECUTION
sur une console lancer le serveur :
$java SSCdayTime 4444

sur une autre console :
$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Wed Jan 11 18:08:10 CET 2006
Connection closed by foreign host.

Les lignes de la classe :

exercices