MIM1
TD 7 de POOGL
Applets et Entrées-sorties

Vincent BOUDET
Bureau 343 (84-70)
email vboudet@ens-lyon.fr

15 mars 2001

A   Rappels et exemples

Les applets sont des programmes Java présentant les caractéristiques suivantes : Pour créer une applet, on étend la classe java.applet.Applet.

Regardons l'exemple suivamt :
import java.awt.*;
public class Bonjour extends java.applet.Applet
{
        String s;
        public void init()
        {
                s="Bonjour";
        }
        public void paint(Graphics g)
        {
                g.drawString(s,80,50);
        }
}
Dans cet exemple, on redéfinit la méthode init. Cette méthode est la première à être appelée lorsqu'on charge l'applet. Ici, nous définissons la chaîne s. Dans un second temps, le navigateur appelle la méthode start que nous n'avons pas redéfini ici. paint est ensuite appelée pour afficher le contexte graphique. Enfin, nous aurions pu définir les méthodes stop (invoquée lorsque le navigateur quitte la page) et destroy (invoquée lorsque le navigateur est quitté).

Pour afficher l'applet, il faut utiliser une page HTML et la balise <APPLET>. Voici un exemple :
<html>
  <body>
    <applet code="Bonjour" width=200 height=150>
    </applet>
  </body>
</html>
Les paramêtres obligatoires sont code, width et height.

Comment passer des paramêtres à une applet ? Pour celà, on utilise la balise <PARAM> et la méthode getParameter.

Question A.1   Modifier l'exmple précédent pour souhaiter la bienvenue à une personne dont le nom est passé en paramêtre dans la page HTML.

B   Utilisation un peu plus avancée

On va créer une applet permettant de dessiner à la souris. Dans notre classe qu'on va appelée Dessin.java nous avons besoin d'un constructeur et de deux gestionnaires d'évènements.

Il faut définir un MouseAdapter pour redéfinir la méthode MousePressed. On veut mémoriser la position courante de la souris qu'on fait un simple clic de la souris.

Question B.1   Créer une classe interne à Dessin étendant MouseAdapter qui définit la méthode mousePressed pour mémoriser la position de la souris.

On veut maintenant tracer les mouvements de la souris quand le bouton de la souris est maintenu enfoncé. Pour celà, nous devons utiliser un MouseMotionListener et plus particulièrement la méthode mouseDragged.

Question B.2   Créer une classe interne à Dessin étendant MouseMotionAdapter qui définit la méthode mouseDragged. Dans cette méthode, on trace un trait entre les valeurs en mémoire de la souris (au dernier clic) et les coordonnées courantes. On met ensuite à jour ces valeurs.

Question B.3   Définisser maintenant (et pour finir) le constructeur Dessin en ajoutant les gestionnaires d'évènements. N'oubliez pas de faire appel au constructeur de la classe Applet.

C   Entrées-sorties

Les entrées et les sorties sont organisées en Java autour du concept de flot (anglais stream), à l'aide d'un ensemble très développé de types. Un flot est une suite de valeurs (octets, caractères, objets quelconques) successivement lues ou écrites. Ces flots sont ainsi classifiés en flots d'entrée (qui comportent des méthodes de lecture), et en flots de sortie (qui comportent des méthodes d'écriture). Outre le programme, un flot d'entrée est connecté à une source, et un flot de sortie à une cible. La source ou la cible d'un flot peut être un fichier, un tampon en mémoire, une chaîne de caractères, un autre flot, une ressource Web ou bien un port Internet.

Les flots les plus basiques sont des flots d'octets. Les classes des flots d'octets en écriture ont un nom en ...OutputStream ; celles des flots d'octets en lecture ont un nom en ...InputStream. Pour travailler avec des flots de caractères Unicode, on utilisera des classes en ...Writer et ...Reader.

C.1   Lire et écrire des flots d'octets

Les méthodes générales de lecture sur un flot d'octets sont : Les méthodes générales d'écriture sur un flot d'octets sont : La lecture et l'écriture d'octets sur un fichier se fait à l'aide des classes FileInputStream et FileOutputStream.
Question C.1   Faites un programme qui copie un fichier dans un autre (dont les noms sont donnés sur la ligne de commande), octet par octet ; si les deux noms de fichiers ne sont pas données sur la ligne de commande, on utilise les flots standards System.in , et System.out (de type PrintStream), ce qui est possible car FileOutputStream et PrintStream sont des sous-classes de OutputStream.

C.2   Lire et écrire sur un flot de caractères

Les flots de caractères sont des objets de classe Reader (flots de caractères d'entrée) ou Writer (flots de caractères de sortie). Les méthodes read et write de ces classes sont analogues à celles opérant sur des flots d'octets, à la différence que c'est un caractère 16 bits qui est lu ou écrit, et non un octet.

La conversion entre un flot d'octets et un flot de caractères se fait à l'aide des classes OutputStreamWriter et InputStreamReader. Cette conversion se fait en connectant un flot d'octets à un flot de caractères :

InputStreamReader isr = new InputStreamReader(System.in);

Cette conversion permet éventuellement de spécifier le codage utilisé (par exemple, par la chaîne "MacSymbol" s'il s'agit d'un codage MacIntosh) :
         InputStreamReader isr =
           new InputStreamReader(
             new FileInputStream("toto"),
             "MacSymbol"
           );
Pour connecter un flot de caractères à un fichier, si cette conversion n'est pas nécessaire, il est plus simple de recourir aux classe FileWriter et FileReader.

C.3   Connecter un flot à un tampon

Chaque opération de lecture ou d'écriture peut être très coûteuse sur certains flots ; c'est notamment le cas des accès à un fichier, ou des accès à l'Internet. Pour éviter des opérations individuelles (sur un octet ou sur un caractère à la fois), on préfère souvent travailler sur un tampon (anglais buffer). Par exemple, pour écrire sur un fichier, on écrira sur un flot-tampon, lequel est connecté à un flot d'écriture sur un fichier.

Les classes qui mettent en oeuvre ces tampons sont : Un flot de caractères de la classe BufferedReader permet des opérations supplémentaires (par exemple, lecture d'une ligne de texte). Il est très courant de connecter un tel tampon à un flot de lecture sur un fichier :

         BufferedReader in =
           new BufferedReader(new FileReader("toto"));
         String s = in.readline();
Symétriquement, pour écrire sur un fichier, il est préférable de travailler avec un tampon :
         PrintWriter out =
           new PrintWriter(
             new BufferedWriter(
               new FileWriter("toto")));
         out.println("un long texte");
Question C.2   Refaites le programme qui copie un fichier en utilisant un flot-tampon.

On peut connecter un flot à une ressource Web. Pour cela, on crée un objet URL qui prend en paramêtre une adresse internet. Dans la classe URL, il existe une méthode openStream.

Question C.3   Écrire un programme qui va chercher le fichier donné par son URL et le recopie dans un autre fichier ou sur la sortie standard.

C.4   Connecter un flot à une socket TCP

On peut aussi connecté un flot d'entrée à un port Internet spécifié par un nom de machine et un numéro de port. Par exemple, le numéro 13, est celui d'un serveur dont la réponse est une ligne contenant la date et l'heure courante. La connexion à ce port utilise le protocole TCP.

Question C.4   Écrire un programme qui se connecte au port 13 de votre machine ou du machine passé en paramêtre (Socket s = new Socket(machine, 13);) lit le flot d'entrée de la socket (getInputStream). Ce flot d'entrée est ensuite transformé en un flot de caractères, puis placé dans un tampon ; la ligne lue sur ce flot d'entrée est simplement copiée sur la sortie standard du programme.

On reviendra sur les flots quand on étudiera les threads et les sockets un peu plus en détail la prochaine fois.


This document was translated from LATEX by HEVEA.