 |
 |
11) Le système d’E/S de Java |
|
 |
|
Texte original |
 |
Traducteur :
Armel Fortun |
|
 |
|
 |
 |
 |
 |
 |
 |
|
 |
|
 |
 |
 |
Circle and Square are
straightforward extensions of Shape; the only difference is that
Circle initializes color at the point of definition and
Square initializes it in the constructor. We’ll leave the
discussion of Line for later.
|
 |
Circle and Square sont des extensions
directes de Shape ; la seule différence est que Circle initialise
color au point de définition et que Square l'initialise dans le
constructeur. Nous laisserons la discussion sur Line pour plus tard.
|
 |
 |
 |
In main( ), one
ArrayList is used to hold the Class objects and the other to hold
the shapes. If you don’t provide a command line argument the
shapeTypes ArrayList is created and the Class objects are
added, and then the shapes ArrayList is created and Shape
objects are added. Next, all the static color values are set to
GREEN, and everything is serialized to the file
CADState.out.
|
 |
Dans main(), une ArrayList est employée
pour tenir les objets de Class et les autres pour tenir les formes. Si vous ne
fournissez pas un argument en ligne de commande la shapeTypes
ArrayList est créé et les objets Class sont ajoutés, et ensuite
l'ArrayList de shapes est créé et les objets
Shape sont ajoutés. Puis, toutes les valeurs static de couleur
(color) sont établies à GREEN, et tout est sérialisé vers le
fichier CADState.out.
|
 |
 |
 |
If you provide a command line argument
(presumably CADState.out), that file is opened and used to restore the
state of the program. In both situations, the resulting ArrayList of
Shapes is printed. The results from one run are:
|
 |
Si l'on fournit un argument en ligne de commande (vraisemblablement
CADState.out), ce fichier est ouvert et utilisé pour restituer l'état du
programme. Dans les deux situations, l'ArrayList de Shapes est
affichée. Le résultat d'une exécution donne :
|
 |
 |
 |
>java CADState
[class Circle color[3] xPos[-51] yPos[-99] dim[38]
, class Square color[3] xPos[2] yPos[61] dim[-46]
, class Line color[3] xPos[51] yPos[73] dim[64]
, class Circle color[3] xPos[-70] yPos[1] dim[16]
, class Square color[3] xPos[3] yPos[94] dim[-36]
, class Line color[3] xPos[-84] yPos[-21] dim[-35]
, class Circle color[3] xPos[-75] yPos[-43] dim[22]
, class Square color[3] xPos[81] yPos[30] dim[-45]
, class Line color[3] xPos[-29] yPos[92] dim[17]
, class Circle color[3] xPos[17] yPos[90] dim[-76]
]
>java CADState CADState.out
[class Circle color[1] xPos[-51] yPos[-99] dim[38]
, class Square color[0] xPos[2] yPos[61] dim[-46]
, class Line color[3] xPos[51] yPos[73] dim[64]
, class Circle color[1] xPos[-70] yPos[1] dim[16]
, class Square color[0] xPos[3] yPos[94] dim[-36]
, class Line color[3] xPos[-84] yPos[-21] dim[-35]
, class Circle color[1] xPos[-75] yPos[-43] dim[22]
, class Square color[0] xPos[81] yPos[30] dim[-45]
, class Line color[3] xPos[-29] yPos[92] dim[17]
, class Circle color[1] xPos[17] yPos[90] dim[-76]
]
|
 |
>java CADState [class Circle color[3] xPos[-51] yPos[-99] dim[38] , class Square color[3] xPos[2] yPos[61] dim[-46] , class Line color[3] xPos[51] yPos[73] dim[64] , class Circle color[3] xPos[-70] yPos[1] dim[16] , class Square color[3] xPos[3] yPos[94] dim[-36] , class Line color[3] xPos[-84] yPos[-21] dim[-35] , class Circle color[3] xPos[-75] yPos[-43] dim[22] , class Square color[3] xPos[81] yPos[30] dim[-45] , class Line color[3] xPos[-29] yPos[92] dim[17] , class Circle color[3] xPos[17] yPos[90] dim[-76] ]
>java CADState CADState.out [class Circle color[1] xPos[-51] yPos[-99] dim[38] , class Square color[0] xPos[2] yPos[61] dim[-46] , class Line color[3] xPos[51] yPos[73] dim[64] , class Circle color[1] xPos[-70] yPos[1] dim[16] , class Square color[0] xPos[3] yPos[94] dim[-36] , class Line color[3] xPos[-84] yPos[-21] dim[-35] , class Circle color[1] xPos[-75] yPos[-43] dim[22] , class Square color[0] xPos[81] yPos[30] dim[-45] , class Line color[3] xPos[-29] yPos[92] dim[17] , class Circle color[1] xPos[17] yPos[90] dim[-76] ]
|
 |
 |
 |
You can see that the values of
xPos, yPos, and dim were all stored and recovered
successfully, but there’s something wrong with the retrieval of the
static information. It’s all “3” going in, but it
doesn’t come out that way. Circles have a value of 1 (RED,
which is the definition), and Squares have a value of 0 (remember, they
are initialized in the constructor). It’s as if the statics
didn’t get serialized at all! That’s right—even though class
Class is Serializable, it doesn’t do what you expect. So if
you want to serialize statics, you must do it yourself.
|
 |
Vous pouvez voir que les valeurs d'xPos,
yPos, et dim sont toutes stockées et récupérées avec succès, mais
qu'il y a quelque chose d'anormal dans la récupération d'informations static. Les
« 3 » rentrent bien, mais ne sortent pas de la même manière. Les Circles
ont une valeur de 1 (RED, ce qui est la définition), et les
Squares ont une valeur de 0 (rappelez-vous, ils sont initialisés dans le
constructeur). C'est comme si les statics n'étaient pas sérialisées du tout ! Ce
qui est correct — malgré que la class Class est
Serializable, cela n'agit pas comme on pouvait l'espérer. Donc si vous désirez
sérialiser des statics, vous devrez le faire vous-même.
|
 |
 |
 |
This is what the
serializeStaticState( ) and deserializeStaticState( )
static methods in Line are for. You can see that they are
explicitly called as part of the storage and retrieval process. (Note that the
order of writing to the serialize file and reading back from it must be
maintained.) Thus to make CADState.java run correctly you
must:
|
 |
C'est à quoi les méthodes static
serializeStaticState() et deserializeStaticState() dans
Line servent. Vous pouvez voir qu'elles sont appelés explicitement comme une
partie du processus de stockage et de récupération. (Notez que l'ordre d'écriture vers le fichier
sérialisé et de sa relecture doit être conservé.) Ainsi pour que CADState.java
s'exécute correctement vous devez :
|
 |
 |
 |
- Add a
serializeStaticState( ) and deserializeStaticState( ) to
the shapes.
- Remove
the ArrayList shapeTypes and all code related to
it.
- Add calls to the
new serialize and deserialize static methods in the
shapes.
|
 |
- Ajouter un serializeStaticState() et un
deserializeStaticState() aux figures [shapes].
- Enlever ArrayList shapeTypes et tout le
code s'y rattachant.
- Ajouter des appels aux nouvelles méthodes statiques de sérialisation et de
sérialisation dans les figures [shapes].
|
 |
 |
 |
Another issue you
might have to think about is security, since serialization also saves
private data. If you have a security issue, those fields should be marked
as transient. But then you have to design a secure way to store that
information so that when you do a restore you can reset those private
variables.
|
 |
Un autre sujet auquel vous devez penser est la sécurité, vu que la
sérialisation sauve aussi les données private. Si vous vous avez orientation de
sécurité, ces champs doivent être marqués comme transient. Mais alors vous devez
concevoir une manière sûre pour stocker cette information de sorte que quand vous faites une
restauration vous pouvez remettre à l'état initial [reset] ces variables
privates.
|
 |
 |
 |
Tokenizing input
|
 |
Tokenizer l'entrée
|
 |
 |
 |
Tokenizing is the process of
breaking a sequence of characters into a sequence of “tokens,” which
are bits of text delimited by whatever you choose. For example, your tokens
could be words, and then they would be delimited by white space and punctuation.
There are two classes provided in the standard Java library that can be used for
tokenization: StreamTokenizer and
StringTokenizer.
|
 |
Tokenizing est le processus de casser une séquence de caractères
en un séquence de « tokens, » qui sont des morceaux de texte délimités par quoi que vous
vous choisissez. Par exemple, vos jetons [tokens] peuvent être des mots, et ensuite ils pourront
être délimités par un blanc et de la ponctuation. Il y a deux classes fournies dans la librairie
standard de Java qui peuvent être employées pour la tokenisation : StreamTokenizer
and StringTokenizer.
|
 |
 |
 |
StreamTokenizer
|
 |
StreamTokenizer
|
 |
 |
 |
Although StreamTokenizer is not
derived from InputStream or OutputStream, it works only with
InputStream objects, so it rightfully belongs in the I/O portion of the
library.
|
 |
Bien que StreamTokenizer ne soit pas dérivé
d'InputStream ou OutputStream, il ne fonctionne qu'avec les
objets InputStreams, donc il appartient à juste titre à la partie d'E/S de la librairie.
|
 |
 |
 |
Consider a program to count the
occurrence of words in a text file:
|
 |
Considérons un programme qui compte les occurrences de mots dans un fichier
texte :
|
 |
 |
 |
//: c11:WordCount.java
// Counts words from a file, outputs
// results in sorted form.
import java.io.*;
import java.util.*;
class Counter {
private int i = 1;
int read() { return i; }
void increment() { i++; }
}
public class WordCount {
private FileReader file;
private StreamTokenizer st;
// A TreeMap keeps keys in sorted order:
private TreeMap counts = new TreeMap();
WordCount(String filename)
throws FileNotFoundException {
try {
file = new FileReader(filename);
st = new StreamTokenizer(
new BufferedReader(file));
st.ordinaryChar('.');
st.ordinaryChar('-');
} catch(FileNotFoundException e) {
System.err.println(
"Could not open " + filename);
throw e;
}
}
void cleanup() {
try {
file.close();
} catch(IOException e) {
System.err.println(
"file.close() unsuccessful");
}
}
void countWords() {
try {
while(st.nextToken() !=
StreamTokenizer.TT_EOF) {
String s;
switch(st.ttype) {
case StreamTokenizer.TT_EOL:
s = new String("EOL");
break;
case StreamTokenizer.TT_NUMBER:
s = Double.toString(st.nval);
break;
case StreamTokenizer.TT_WORD:
s = st.sval; // Already a String
break;
default: // single character in ttype
s = String.valueOf((char)st.ttype);
}
if(counts.containsKey(s))
((Counter)counts.get(s)).increment();
else
counts.put(s, new Counter());
}
} catch(IOException e) {
System.err.println(
"st.nextToken() unsuccessful");
}
}
Collection values() {
return counts.values();
}
Set keySet() { return counts.keySet(); }
Counter getCounter(String s) {
return (Counter)counts.get(s);
}
public static void main(String[] args)
throws FileNotFoundException {
WordCount wc =
new WordCount(args[0]);
wc.countWords();
Iterator keys = wc.keySet().iterator();
while(keys.hasNext()) {
String key = (String)keys.next();
System.out.println(key + ": "
+ wc.getCounter(key).read());
}
wc.cleanup();
}
} ///:~
|
 |
//: c11:WordCount.java // Compte les mots dans un fichier, produit // les résultats dans un formulaire classé. import java.io.*; import java.util.*;
class Counter { private int i = 1; int read() { return i; } void increment() { i++; } }
public class WordCount { private FileReader file; private StreamTokenizer st; // Un TreeMap conserve les clés dans un ordre classé : private TreeMap counts = new TreeMap(); WordCount(String filename) throws FileNotFoundException { try { file = new FileReader(filename); st = new StreamTokenizer( new BufferedReader(file)); st.ordinaryChar('.'); st.ordinaryChar('-'); } catch(FileNotFoundException e) { System.err.println( "Could not open " + filename); throw e; } } void cleanup() { try { file.close(); } catch(IOException e) { System.err.println( "file.close() unsuccessful"); } } void countWords() { try { while(st.nextToken() != StreamTokenizer.TT_EOF) { String s; switch(st.ttype) { case StreamTokenizer.TT_EOL: s = new String("EOL"); break; case StreamTokenizer.TT_NUMBER: s = Double.toString(st.nval); break; case StreamTokenizer.TT_WORD: s = st.sval; // Déjà un String break; default: // un seul caractère dans type s = String.valueOf((char)st.ttype); } if(counts.containsKey(s)) ((Counter)counts.get(s)).increment(); else counts.put(s, new Counter()); } } catch(IOException e) { System.err.println( "st.nextToken() unsuccessful"); } } Collection values() { return counts.values(); } Set keySet() { return counts.keySet(); } Counter getCounter(String s) { return (Counter)counts.get(s); } public static void main(String[] args) throws FileNotFoundException { WordCount wc = new WordCount(args[0]); wc.countWords(); Iterator keys = wc.keySet().iterator(); while(keys.hasNext()) { String key = (String)keys.next(); System.out.println(key + ": " + wc.getCounter(key).read()); } wc.cleanup(); } } ///:~
|
 |
 |
 |
Presenting the words in sorted form is
easy to do by storing the data in a TreeMap, which automatically
organizes its keys in sorted order (see Chapter 9). When you get a set of
keys using keySet( ), they will also be in sorted
order.
|
 |
Présenter les mots sous une forme classée est facile à faire en stockant
les données dans un TreeMap, qui organise automatiquement ces clés dans un ordre classé (voir le
Chapitre 9). Quand vous avez un jeu de clés en utilisant keySet() , elles seront
automatiquement rangées dans l'ordre.
|
 |
 |
 |
To open the file, a FileReader is
used, and to turn the file into words a StreamTokenizer is created from
the FileReader wrapped in a BufferedReader. In
StreamTokenizer, there is a default list of separators, and you can add
more with a set of methods. Here, ordinaryChar( ) is used to say
“This character has no significance that I’m interested in,”
so the parser doesn’t include it as part of any of the words that it
creates. For example, saying st.ordinaryChar('.') means that periods will
not be included as parts of the words that are parsed. You can find more
information in the JDK HTML documentation from
java.sun.com.
|
 |
Pour ouvrir le fichier, un FileReader est utilisé, et pour
changer le fichier en mots un StreamTokenizer est créé depuis le
FileReader enveloppé dans un BufferedReader. Dans
StreamTokenizer, il y a une liste par défaut de séparateurs, et vous pouvez en
ajouter d'autres avec un jeu de méthodes. Ici, ordinaryChar() est utilisé pour
dire « Ce caractère n'a aucune signification pour que je m'y intéresse, » donc
l'analyseur ne les incluras pas comme des parties de tous les mots qu'il va créer. Par exemple,
dire st.ordinaryChar('.') veut dire que les points ne seront pas inclus comme des
parties des mots qui seront analysés. Vous pourrez trouver plus d'information dans la documentation
HTML du JDK à <java.sun.com>.
|
 |
 |
 |
In countWords( ), the tokens
are pulled one at a time from the stream, and the ttype information is
used to determine what to do with each token, since a token can be an
end-of-line, a number, a string, or a single character.
|
 |
Dans countWords(), les tokens sont tirés un à un depuis le
stream, et l'information ttype est utilisée pour déterminer ce qu'il faut faire
avec chaque token, vu qu'un token peut être une fin de ligne, un nombre, une chaîne de caractère
[string], ou un simple caractère.
|
 |
 |
 |
Once a token is found, the
TreeMap counts is queried to see if it already
contains the token as a key. If it does, the corresponding Counter object
is incremented to indicate that another instance of this word has been found. If
not, a new Counter is created—since the Counter constructor
initializes its value to one, this also acts to count the word.
|
 |
Une fois qu'un token est trouvé, le counts de
TreeMap est appelé pour voir si il contient déjà le token sous la forme d'une clé.
Si c'est le cas, l'objet Counter correspondant est incrémenté pour indiquer qu'une
autre instance de ce mots a été trouvée. Si ce n'est pas le cas, un nouveau
Counter est créé — vu que le constructeur de Counter
initialise sa valeur à un, ceci agit aussi pour compter le mot.
|
 |
 |
 |
WordCount is not a type of
TreeMap, so it wasn’t inherited. It performs a specific type of
functionality, so even though the keys( ) and values( )
methods must be reexposed, that still doesn’t mean that
inheritance should be used since
a number of TreeMap methods are inappropriate here. In addition, other
methods like getCounter( ), which get the Counter for a
particular String, and sortedKeys( ), which produces an
Iterator, finish the change in the shape of WordCount’s
interface.
|
 |
WordCount n'est pas un type de TreeMap,
donc il n'est pas hérité. Il accompli un type de fonctionnalité spécifique, ainsi bien que les
méthodes keys() et values() doivent être re-exposées, cela ne
veut pas forcément dire que l'héritage doit être utilisé vu qu'un bon nombre de méthodes de
TreeMap sont ici inappropriés. En plus, les autres méthodes comme
getCounter(), qui prend le Counter pour un
String particulier, et sortedKeys(), qui produit un
Iterator, terminant le changement dans la forme d'interface de
WordCount..
|
 |
 |
 |
In main( ) you can see the
use of a WordCount to open and count the words in a file—it just
takes two lines of code. Then an Iterator to a sorted list of keys (words) is
extracted, and this is used to pull out each key and associated Count.
The call to cleanup( ) is necessary to ensure that the file is
closed.
|
 |
Dans main() vous pouvez voir l'emploi d'un WordCount pour
ouvrir et compter les mots dans un fichier — cela ne prend que deux lignes de code. Puis un
Iterator est extrait vers une liste triée de clés (mots), et est employé pour
retirer chaque clé et Count associés. L'appel à cleanup() est
nécessaire pour s'assurer que le fichier est fermé.
|
 |
 |
 |
StringTokenizer
|
 |
StringTokenizer
|
 |
 |
 |
Although it isn’t part of the I/O
library, the StringTokenizer has sufficiently similar functionality to
StreamTokenizer that it will be described here.
|
 |
Bien qu'il ne fasse pas partie de la bibliothèque d'E/S, le
StringTokenizer possède des fonctions assez similaires a
StreamTokenizer comme il sera décrit ici.
|
 |
 |
 |
The
StringTokenizer returns the tokens within a
string one at a time. These tokens are consecutive characters delimited by tabs,
spaces, and newlines. Thus, the tokens of the string “Where is my
cat?” are “Where”, “is”, “my”, and
“cat?” Like the StreamTokenizer, you can tell the
StringTokenizer to break up the input in any way that you want, but with
StringTokenizer you do this by passing a second argument to the
constructor, which is a String of the delimiters you wish to use. In
general, if you need more sophistication, use a
StreamTokenizer.
|
 |
Le StringTokenizer renvoie les tokens dans une chaîne de
caractère un par un. Ces tokens sont des caractères consécutifs délimités par des tabulations, des
espaces, et des nouvelles lignes. Ainsi, les tokens de la chaîne de caractère « Où est mon
chat ? » sont « Où, » « est, » « mon, » « chat, »
« ?. » Comme le StreamTokenizer, vous pouvez appeler le
StringTokenizer pour casser l'entrée de n'importe quelle manière, mais avec
StringTokenizer vous effectuez cela en passant un second argument au constructeur,
qui est un String des délimiteurs que vous utiliserez. En général, si vous désirez
plus de sophistication, employez un StreamTokenizer.
|
 |
 |
 |
You ask a StringTokenizer object
for the next token in the string using the nextToken( ) method,
which either returns the token or an empty string to indicate that no tokens
remain.
|
 |
Vous appelez un objet StringTokenizer pour le prochain
token dans la chaîne de caractère en utilisant la méthode nextToken(), qui renvoie
soit un token ou une chaîne de caractère vide pour indiquer qu'il ne reste pas de
tokens.
|
 |
 |
 |
As an example, the following program
performs a limited analysis of a sentence, looking for key phrase sequences to
indicate whether happiness or sadness is implied.
|
 |
Comme exemple, le programme suivant exécute une analyse limitée d'une
phrase, cherchant des phrases clés pour indiquer si la joie ou la tristesse sont
sous-entendues.
|
 |
 |
 |
//: c11:AnalyzeSentence.java
// Look for particular sequences in sentences.
import java.util.*;
public class AnalyzeSentence {
public static void main(String[] args) {
analyze("I am happy about this");
analyze("I am not happy about this");
analyze("I am not! I am happy");
analyze("I am sad about this");
analyze("I am not sad about this");
analyze("I am not! I am sad");
analyze("Are you happy about this?");
analyze("Are you sad about this?");
analyze("It's you! I am happy");
analyze("It's you! I am sad");
}
static StringTokenizer st;
static void analyze(String s) {
prt("\nnew sentence >> " + s);
boolean sad = false;
st = new StringTokenizer(s);
while (st.hasMoreTokens()) {
String token = next();
// Look until you find one of the
// two starting tokens:
if(!token.equals("I") &&
!token.equals("Are"))
continue; // Top of while loop
if(token.equals("I")) {
String tk2 = next();
if(!tk2.equals("am")) // Must be after I
break; // Out of while loop
else {
String tk3 = next();
if(tk3.equals("sad")) {
sad = true;
break; // Out of while loop
}
if (tk3.equals("not")) {
String tk4 = next();
if(tk4.equals("sad"))
break; // Leave sad false
if(tk4.equals("happy")) {
sad = true;
break;
}
}
}
}
if(token.equals("Are")) {
String tk2 = next();
if(!tk2.equals("you"))
break; // Must be after Are
String tk3 = next();
if(tk3.equals("sad"))
sad = true;
break; // Out of while loop
}
}
if(sad) prt("Sad detected");
}
static String next() {
if(st.hasMoreTokens()) {
String s = st.nextToken();
prt(s);
return s;
}
else
return "";
}
static void prt(String s) {
System.out.println(s);
}
} ///:~
|
 |
//: c11:AnalyzeSentence.java // Cherche des séries particulières dans les phrases. import java.util.*;
public class AnalyzeSentence { public static void main(String[] args) { analyze("I am happy about this"); analyze("I am not happy about this"); analyze("I am not! I am happy"); analyze("I am sad about this"); analyze("I am not sad about this"); analyze("I am not! I am sad"); analyze("Are you happy about this?"); analyze("Are you sad about this?"); analyze("It's you! I am happy"); analyze("It's you! I am sad"); } static StringTokenizer st; static void analyze(String s) { prt("\nnew sentence >> " + s); boolean sad = false; st = new StringTokenizer(s); while (st.hasMoreTokens()) { String token = next(); // Cherche jusqu'à ce l'on trouve un des // deux tokens de départ : if(!token.equals("I") && !token.equals("Are")) continue; // Haut de la boucle while if(token.equals("I")) { String tk2 = next(); if(!tk2.equals("am")) // Doit être après I break; // Sortie de la boucle while else { String tk3 = next(); if(tk3.equals("sad")) { sad = true; break; // Sortie de la boucle while } if (tk3.equals("not")) { String tk4 = next(); if(tk4.equals("sad")) break; // Laisse sad faux if(tk4.equals("happy")) { sad = true; break; } } } } if(token.equals("Are")) { String tk2 = next(); if(!tk2.equals("you")) break; // Doit être après Are String tk3 = next(); if(tk3.equals("sad")) sad = true; break; // Sortie de la boucle while } } if(sad) prt("Sad detected"); } static String next() { if(st.hasMoreTokens()) { String s = st.nextToken(); prt(s); return s; } else return ""; } static void prt(String s) { System.out.println(s); } } ///:~
|
 |
 |
 |
For each string being analyzed, a
while loop is entered and tokens are pulled off the string. Notice the
first if statement, which says to continue (go back to the
beginning of the loop and start again) if the token is neither an
“I” nor an “Are.” This means
that it will get tokens until an “I” or an “Are” is
found. You might think to use the == instead of the
equals( ) method,
but that won’t work correctly, since == compares reference values
while equals( ) compares contents.
|
 |
Pour que chaque chaîne de caractère soit analysée, une boucle
while est entrée et les tokens sont poussés hors de la chaîne de caractères. Notez
la première déclaration de if, qui dit de continuer (retourne au
début de la boucle et recommence encore) si le token est ni un « I » ou un
« Are. » Ceci signifie qu'il attrapera les tokens que si un « I » ou un
« Are » est trouvé. Vous pourriez penser utiliser le == à la place de la méthode
equals(), mais cela ne fonctionne pas correctement, comme == compare les
références de valeur tandis qu'equals() compare les contenus.
|
 |
 |
 |
The logic of the rest of the
analyze( ) method is that the pattern that’s being searched
for is “I am sad,” “I am not happy,” or “Are you
sad?” Without the break statement, the code for this would be even
messier than it is. You should be aware that a typical parser (this is a
primitive example of one) normally has a table of these tokens and a piece of
code that moves through the states in the table as new tokens are
read.
|
 |
La logique du reste de la méthode analyze() est que le
pattern (motif) dont on recherche la présence est « I am sad, » « I am not
happy, » or « Are you sad? » Sans la déclaration break, le code
réalisant ça serait bien plus confus qu'il ne l'est. Vous devez être conscient qu'un parseur
typique (ceci en est un exemple primitif) possède normalement une table de ces tokens et un morceau
de code qui bouge de l'un à l'autre des statuts dans la table quand les nouveaux tokens sont
lus.
|
 |
 |
 |
You should think of the
StringTokenizer only as shorthand for a simple and specific kind of
StreamTokenizer. However, if you have a String that you want to
tokenize and StringTokenizer is too limited, all you have to do is turn
it into a stream with StringBufferInputStream and then use that to create
a much more powerful
StreamTokenizer.
|
 |
Vous pourrez voir le StringTokenizer seulement comme un
raccourci pour un type de StreamTokenizer simple et spécifique. Cependant, si vous
avez un String que vous désirez tokenizer et que StringTokenizer
est trop limité, tout ce que vous avez à faire est de le retourner dans un flux avec
StringBufferInputStream puis de l'utiliser pour créer un
StreamTokenizer beaucoup plus puissant.
|
 |
 |
 |
Checking capitalization style
|
 |
Vérifier le style de capitalization
|
 |
 |
 |
In this section we’ll look at a
more complete example of the use of Java I/O, which also uses tokenization.
This project is directly useful
because it performs a style check to make sure that your capitalization conforms
to the Java style as found at java.sun.com/docs/codeconv/index.html. It
opens each .java file in the current directory and extracts all the class
names and identifiers, then shows you if any of them don’t meet the Java
style.
|
 |
Dans cette partie on observera un exemple un peut plus complet
d'utilisation du Java E/S. Ce projet est directement utile puisqu'il accomplit une vérification de
style pour être sur que la capitalisation se conforme au style Java comme décrit
surjava.sun.com/docs/codeconv/index.html. Il ouvre chaque fichier .java
dans le répertoire courant et extrait tous les noms de classe et d'identifiants, puis nous indique
si affiche l'un d'entre eux ne correspond pas au style Java.
|
 |
 |
 |
For the program to operate correctly, you
must first build a class name repository to hold all the class names in the
standard Java library. You do this by moving into all the source code
subdirectories for the standard Java library and running ClassScanner in
each subdirectory. Provide as arguments the name of the repository file (using
the same path and name each time) and the -a command-line option to
indicate that the class names should be added to the
repository.
|
 |
Afin que le programme s'exécute correctement, on devra d'abord construire
un dépôt de noms de classes pour conserver tous les noms de classes dans la bibliothèque standard
de Java. On réalise ceci en se déplaçant dans tous les sous-répertoires du code source de la
bibliothèque standard Java et en exécutant ClassScanner dans chaque sous
répertoire. Donnant comme arguments le nom du fichier dépositaire (utilisant le même chemin et nom
chaque fois) et l'option -lign de commande -a pour indiquer que les noms de
classes devront être ajoutés au dépôt.
|
 |
 |
 |
To use the program to check your code,
hand it the path and name of the repository to use. It will check all the
classes and identifiers in the current directory and tell you which ones
don’t follow the typical Java capitalization style.
|
 |
Afin d'utiliser le programme pour vérifier votre code, indiquez lui le
chemin et le nom du dépôt à employer. Il vérifiera toutes les classes et les identifiants du
répertoire courant et vous vous dira lesquels ne suivent pas le style de capitalisation
Java.
|
 |
 |
 |
You should be aware that the program
isn’t perfect; there are a few times when it will point out what it thinks
is a problem but on looking at the code you’ll see that nothing needs to
be changed. This is a little annoying, but it’s still much easier than
trying to find all these cases by staring at your code.
|
 |
Vous devrez être conscient que ce programme n'est pas parfait ; il y a
quelques fois ou il signalera ce qui lui semble être un problème mais en regardant le code vous
verrez qu'il n'y a rien à changer. C'est quelque peut agaçant, mais c'est tellement plus simple que
d'essayer de trouver tous ces cas en vérifiant de vos yeux votre code.
|
 |
 |
 |
 |
 |
 |
 |
 |
|
 |
 |
 |