Bonjour,
Je cherche à réaliser une classe permettant de lire simplement un flux provenant d'un fichier ou d'une socket.
Pour cela, j'ai commencé à créer la fonction readAll(BufferedReader), qui permet de lire entièrement le contenu du flux.
Remarque : Je ne peux utiliser la fonction BufferedReader.readLine() car il m'est impossible de connaitre le caractère qui a provoqué la sortie de la fonction ('\r', '\n' ou '\r' suivi de '\n'), a moins de lire 2 fois le flux et de stocker les positions des fins de ligne (ce qui me semble impossible pour les sockets).
Je n'ai pas non plus opté pour une lecture caractère par caractère, étant donné la lenteur du traitement. J'ai donc choisi d'utiliser la fonction BufferedReader.read(char[]) avec un buffer assez grand pour ameliorer la vitesse (même si ça ne me satisfais pas vraiment, en comparaison avec le readLine(), qui reste plus rapide).
Voici donc le code actuel de la fonction readAll(BufferedReader) (je l'ai mise en static pour les tests):
Même si je n'ai pas une grande expérience du Java, je ne pense pas m'être trompé ici.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 public static String readAll(BufferedReader reader) throws IOException, NullPointerException { char[] buffer = new char[1024 * 8]; StringBuilder builder = new StringBuilder(); int len = 0; if(reader == null) throw new NullPointerException("Erreur fonction readAll(BufferedReader) : le parametre vaut null."); try { while((len = reader.read(buffer)) > 0) builder.append(String.valueOf(buffer), 0, len); } catch(IOException eRead) { throw new IOException("Erreur fonction readAll(BufferedReader) : Une erreur est survenue lors de la lecture du reader.", eRead.getCause()); } finally { try { reader.close(); } catch(IOException eClose) { throw new IOException("Erreur fonction readAll(BufferedReader) : Une erreur est survenue lors de la fermeture du reader.", eClose.getCause()); } } return builder.toString(); }
Pour vérifier que cette fonction s'exécute correctement, j'ai donc créé une fonction write(BufferedWriter, String), toujours en static, dont voici le code :
Rien (je pense) de compliqué ici non plus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 public static void write(BufferedWriter writer, String donnees) throws IOException, NullPointerException { if(donnees == null) throw new NullPointerException("Erreur fonction write(BufferedWriter, String) : la chaine en parametre vaut null."); if(writer == null) throw new NullPointerException("Erreur fonction write(BufferedWriter, String) : le writer en parametre vaut null."); try { writer.write(donnees); try { writer.flush(); } catch(IOException eFlush) { throw new IOException("Erreur fonction write(BufferedWriter, String) : impossible de flush().", eFlush.getCause()); } } catch(IOException eWrite) { throw new IOException("Erreur fonction write(BufferedWriter, String) : impossible d'ecrire dans le writer.", eWrite.getCause()); } finally { try { writer.close(); } catch(IOException eClose) { throw new IOException("Erreur fonction write(BufferedWriter, String) : Une erreur est survenue lors de la fermeture du writer.", eClose.getCause()); } } }
Je teste donc ces deux fonction grâce à ce main :Je ne teste pas l'existence des fichiers, ni s'il s'agit de répertoires, je sais que je ne me suis pas trompé ici. Je n'ai pas mis de commentaires non plus mais j'ai essayé de rendre parlantes les Exceptions.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 public static void main(String[] args) { String s = null, entree = "C:\\UN\\FICHIER\\EXECUTABLE\\A\\COPIER.exe", sortie = "C:\\UN\\FICHIER\\EXECUTABLE\\COPIE.exe"; System.out.println("Debut Programme"); try { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File(entree)))); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(sortie)))); s = readAll(br); write(bw, s); System.out.println("Ecriture Ok"); } catch(Exception e) { e.printStackTrace(); } System.out.println("Fin Programme"); }
Je tiens aussi à préciser que je n'ai réalisé aucun test sur des sockets, donc il est possible que cela ne fonctionne pas avec celles ci.
Lors de l'exécution du code, aucune exception n'est levée, mais j'obtiens un problème : certain caractères "apparaissent" dans le fichier de sortie, lorsque je compare les fichiers avec un éditeur de texte (Notepad++). Il s'agit en fait de points d'interrogation qui apparaissent indépendamment de la taille du buffer et des caractères qui précèdent et qui suivent, mais qui se retrouvent toujours aux mêmes endroits.
Après beaucoup de tests, il semble que cela vienne du reader.read(buffer), et non pas du passage du char[] au StringBuilder comme je le pensais au départ.
J'ai pensé aussi qu'il pouvait s'agir d'un problème d'encodage mais les points d'interrogation "apparaissent" bien : je veux dire par là que les deux caractères qui les entourent dans le fichier de sortie sont bien présents dans le fichier d'entrée, mais qu'il sont collés dans le fichier d'entrée.
Je commence sérieusement à désespérer après plusieurs heures de recherches sur des solutions ou des manières alternatives, je pensais être moins embêté pour simplement copier des fichiers.
Cordialement.
Partager