Créer tableau uniforme dans un fichier Texte (JAVA) [Résolu]

skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 22 mai 2011 à 11:07 - Dernière réponse : Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention
- 23 mai 2011 à 10:05
Bonjour tous le monde.

J'aimerai créer un tableau (en ascii) dans un fichier texte du style :
CONTEXT                       |TRAITE         |A_APPLIQUER    |
--------------------------------------------------------------|
1erContexte                   |20             |5              |
2eContexte                    |20             |5              |
3eContexte                    |205400000000000|5              |
4eContexte                    |8              |511454152121211|
5eContexteTresLonggggggggggggg|8              |511454152121211|


Pour cela je dispose d'une classe StatsActes que j'ai créé:
public class StatsActes {

private String contexte;
private String etat;
private String nombre;
//Je vous épargne mes getters et setters.
}


Sur une requête en base, je récupère une List<StatsActes>, puis je la transforme en HashMap<String, Set<StatsActes>> pour trier tout ceci par contexte.

HashMap<String, Set<StatsActes>> map = new HashMap<String, Set<StatsActes>>();
  
        for (StatsActes stats : statsActes) {
            String context = stats.getContexte();
            Set<StatsActes> sa = new HashSet<StatsActes>();
            sa.add(stats);
            if(!map.containsKey(context)){
                map.put(context, sa);
              }
               else{
                   map.get(context).add(stats);
               }
        }


Ce que j'aimerai, c'est créer mon tableau comme ci dessus mais en tenant compte de la longueur des mes champs pour avoir un tableau uniforme pour pouvoir lire mon fichier correctement et pas chercher la colonne comme du genre :
CONTEXT|TRAITE|A_APPLIQUER|
--------------------------|
1erContexte|20|5|
2eContexte|20|5|
3eContexte|205400000000000|5|
4eContexte |8|511454152121211|
5eContexteTresLonggggggggggggg|8|511454152121211|


(Je précise l'entête : CONTEXT = contexte de ma classe StatsActes, TRAITE et A_APPLIQUER sont les états que je récupère de StatsActes aussi)

Pour la création de mon fichier texte, je n'ai pas le choix, je dois utiliser les librairies standards. Personnellement j'utilise ceci :
OutputStream outputStream = new FileOutputStream(new  File("./File.txt"));
Writer writer = new OutputStreamWriter(outputStream);


Voila j'espère avoir été assez clair sur mon besoin. Si vous voulez plus d'informations n'hésitez pas! Merci d'avance à tous le monde
Afficher la suite 

Votre réponse

10 réponses

Meilleure réponse
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 23 mai 2011 à 10:05
3
Merci
Salut,

Si tu t'es basé sur ma méthode writeInFile l'ordre de tes champs se trouve là ou il y a les writeItem(...).



------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO

Merci Twinuts 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 102 internautes ce mois-ci

Commenter la réponse de Twinuts
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 22 mai 2011 à 12:01
0
Merci
Salut,

Pourquoi te prendre la tête avec la longueur de tes champs ?
Tu fais une lecture de ton fichier (sans les 2 premières lignes) ligne à ligne et pour chaque ligne tu utilises StringTokenizer

exemple:

fichier test.txt
CONTEXT|TRAITE|A_APPLIQUER|
--------------------------|
1erContexte|20|5|
1erContexte|30|10|
2eContexte|20|5|
3eContexte|205400000000000|5|
4eContexte |8|511454152121211|
5eContexteTresLonggggggggggggg|8|511454152121211|



Classe permettant de parser le fichier et d'afficher la table:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
import java.util.StringTokenizer;

public class Test {

public static void main(final String[] args) {
final Test t = new Test();
HashMap<String, Set<StatsActes>> map = null;
try {
map = t.loadFromFile(new File("Test.txt"));
} catch (final FileNotFoundException e) {
e.printStackTrace();
}
t.print(map);
}

public HashMap<String, Set<StatsActes>> loadFromFile(final File file)
throws FileNotFoundException {
final HashMap<String, Set<StatsActes>> map = new HashMap<String, Set<StatsActes>>();
final Scanner sc = new Scanner(file);
int lines = 0; // pour ne pas traiter les 2 premieres lignes
StringTokenizer token = null; // pour parser les champs
Set<StatsActes> sa = null;
StatsActes item = null;
while (sc.hasNextLine()) {
final String line = sc.nextLine();
if (lines < 2) {
lines++;
continue;
}
token = new StringTokenizer(line, "|");
// récupération des données avec un petit test
final String context = token.hasMoreTokens() ? token.nextToken() : "Error";
final String etat = token.hasMoreTokens() ? token.nextToken() : "Error";
final String nombre = token.hasMoreTokens() ? token.nextToken() : "Error";
sa = new HashSet<StatsActes>();
// j'ai ajouté le constructeur
// public StatsActes(final String contexte, final String etat, final
// String nombre)
item = new StatsActes(context, etat, nombre);

if (!map.containsKey(context)) {
sa.add(item);
map.put(context, sa);
} else
map.get(context).add(item);
}
sc.close();
return map;
}

public void print(final HashMap<String, Set<StatsActes>> map) {
final Set<String> keys = map.keySet();
for (final String key : keys) {
System.err.println(key);
final Set<StatsActes> value = map.get(key);
for (final StatsActes v : value) {
// j'ai redef toString
// public String toString() {
// return contexte + "|" + etat + "|" + nombre;
// }
System.err.println("\tv: " + v);
}
}

}
}






------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Commenter la réponse de Twinuts
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 22 mai 2011 à 12:04
0
Merci
Re,

Tite coquille, la ligne "sa = new HashSet<StatsActes>();" est a placer dans le "if (!map.containsKey(context))" pour éviter l'allocation si l'item est déjà présent.





------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Commenter la réponse de Twinuts
skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 22 mai 2011 à 12:23
0
Merci
Le problème est que je n'ai pas de fichier au départ, c'est moi qui veut créer ce beau tableau.
Commenter la réponse de skold
skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 22 mai 2011 à 12:24
0
Merci
Petit précision, ce qu'il y a dans ma List<StatsActes> est le résultat d'une requête sur une base oracle.
Commenter la réponse de skold
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 22 mai 2011 à 12:37
0
Merci
Salut,


Le problème est que je n'ai pas de fichier au départ, c'est moi qui veut créer ce beau tableau.

Bah quoi ? il est ou le pb ? tu ajoutes une méthode pour générer un fichier ayant la même structure que ton fichier d'exemple... ce qui est fait dans le print peut facilement etre remplacé par une méthode write genre:
public void writeInFile(final HashMap<String, Set<StatsActes>> map, final File file) throws FileNotFoundException {
  PrintWriter pw = new PrintWriter(file);
  pw.println("CONTEXT|TRAITE|A_APPLIQUER|");
  pw.println("--------------------------|");
  pw.flush();
  final Set<String> keys = map.keySet();
  for (final String key : keys) {
    final Set<StatsActes> value = map.get(key);
    for (final StatsActes v : value) {
      pw.println(v.toString());
      pw.flush();
    }
  }
  pw.close();
}




Petit précision, ce qu'il y a dans ma List<StatsActes> est le résultat d'une requête sur une base oracle.

Adapte le code, je ne t'ai pas donné le code ci-dessus pour te faire ton boulot mais uniquement pour te montrer les bases (principalement le StringTokenizer).


------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Commenter la réponse de Twinuts
skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 22 mai 2011 à 13:52
0
Merci
Pourquoi ce baser sur un fichier d'exemple car au stade où je veux construire mon fichier je n'ai pas de fichier d'exemple, juste ma liste. Le premier que je vous ai montré (1er de mon premier post) est le fichier que je veux avoir justement. J'ai fais des essais en parcourant la map comme toi, seulement j'obtiens le résultat suivant:

CONTEXT|TRAITE|A_APPLIQUER|
--------------------------|
1erContexte|20|5|
2eContexte|20|5|
3eContexte|205400000000000|5|
4eContexte |8|511454152121211|
5eContexteTresLonggggggggggggg|8|511454152121211|


Ce que je veux c'est que les colonnes prennent la taille maximum de mes champs pour que tout soit aligné.

Au final je veux :

CONTEXT                       |TRAITE         |A_APPLIQUER    |
--------------------------------------------------------------|
1erContexte                   |20             |5              |
2eContexte                    |20             |5              |
3eContexte                    |205400000000000|5              |
4eContexte                    |8              |511454152121211|
5eContexteTresLonggggggggggggg|8              |511454152121211|
Commenter la réponse de skold
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 22 mai 2011 à 14:45
0
Merci
Salut,

Tiens fait à l’arrache:
private enum Type {
CONTEXTE,
ETAT,
NOMBRE;
}

public void writeInFile(final HashMap<String, Set<StatsActes>> map, File file) throws FileNotFoundException {
PrintWriter pw = new PrintWriter(file);
pw.println("CONTEXT|TRAITE|A_APPLIQUER|");
pw.println("--------------------------|");
pw.flush();
int space_context = getMax(map, Type.CONTEXTE);
int space_etat = getMax(map, Type.ETAT);
int space_nb = getMax(map, Type.NOMBRE);
final Set<String> keys = map.keySet();
for (final String key : keys) {
final Set<StatsActes> value = map.get(key);
for (final StatsActes v : value) {
writeItem(pw, v.getContexte(), space_context);
writeItem(pw, v.getEtat(), space_etat);
writeItem(pw, v.getNombre(), space_nb);
pw.println();
pw.flush();
}
}
pw.close();
}

private void writeItem(PrintWriter pw, String input, int max) {
if(input.length() < max) {
pw.print(input);
pw.print(getSpaces(max - input.length()));
pw.print(" |");
} else
pw.print(input + " |");
}

private String getSpaces(int nb) {
String ret = "";
for(int i = 0; i < nb; ++i)
ret += " ";
return ret;
}

private int getMax(final HashMap<String, Set<StatsActes>> map, Type type) {
final Set<String> keys = map.keySet();
int len = 0;
for (final String key : keys) {
final Set<StatsActes> value = map.get(key);
for (final StatsActes v : value) {
switch(type) {
case CONTEXTE:
if(v.getContexte().length() > len) len = v.getContexte().length();
break;
case ETAT:
if(v.getEtat().length() > len) len = v.getEtat().length();
case NOMBRE:
if(v.getNombre().length() > len) len = v.getNombre().length();
}
}
}
return len;
}



C'est juste pour le principe, mais il va de soit que ce codes n'est absolument pas viable dans le cas ou tu as un très grand nombre d'entrées et idéalement il faudrait que les compteurs space_xxx soient automatiquement renseignés au moment de ta lecture de base afin de gagner énormément de temps.
Ensuite vu que j'utilise un espace, si le viewer n'a pas de font monospace il y aura un décalage, cela dit tu peux remplacer les espaces par \t mais la encore ça dépend du viewer... exemple sous eclipse tu peux redef le nb d'espaces max que représente une tab.



------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Commenter la réponse de Twinuts
skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 22 mai 2011 à 19:08
0
Merci
C'est pas tout à fait ce que je veux mais cela m'aide beaucoup! Je vais partir de ton bout de code pour le continuer. Merci beaucoup!
Commenter la réponse de skold
skold 6 Messages postés samedi 11 décembre 2004Date d'inscription 31 juillet 2011 Dernière intervention - 23 mai 2011 à 09:11
0
Merci
Le problème est que le nombre que je récupère n'est pas forcément au bon endroit (dans la bonne colonne). Aujourd'hui je suis à ce stade :

CONTEXTE          |ENREGISTRE |TRAITE |FINALISE |A_INFORMER |
SIREN_0_IMM       |2 |
MAINTOFFRES_2_CYC |1 |
MAINTPRS_1_IMM    |1 |
SIREN_2_IMM       |1 |
MAINTOFFRES_1_IMM |1 |
SIREN_1_IMM       |1 |
MAINTOFFRES_2_EFF |1 |
MAINTOFFRES_2_IMM |2 |



Le nombre en gras par exemple ne doit pas ce trouver dans la colonne enregistrer, mais dans finaliser. Il y a un histoire de position mais je suis un peux perdu.
Commenter la réponse de skold

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.