IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Lecture par bouts de chaînes de longueur variable


Sujet :

avec Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut Lecture par bouts de chaînes de longueur variable
    Bonjour.

    Une question, svp. Mon applic reçoit différents fichiers texte au format csv étant caractérisés par:
    - Lignes de longueur variable (20 à 23 caractères, y compris le '\n' invisible de fin de ligne).
    Essentiellement des valeurs décimales.
    - De ± 15.000 à ± 35.000 lignes
    - Chaque ligne comprend 2 champs terminés par ';'
    - Se terminant par 'EOF' (-1).
    La finalité est de remplir une table apparaissant dans un GUI Swing.

    1) Je voudrais savoir quelles instructions Java employer ...
    - pour lire les fichiers (± 807.000octets) par bouts de chaînes de caractères de longueur variable, c à d s'arrêtant chaque fois au '\n' (20 à 23 car.)
    - pour si possible mettre chaque nouvelle chaîne lue dans le tampon de caractères consécutif d'une ByteBuffer[]. Cette Array serait initialement implémentée à [15.000][23], et serait aggrandie dynamiquement (malloc()) par groupes de 10 tampons (de 23 octets) au besoin.
    Je viens d'étudier les classes 'File', 'FileInputStream', 'FileChannel', ... et fonctions
    'canalFichier.read(ByteBuffer[] tamponsLect, int offset, int longueur) ... mais elles ne me permettent pas de réaliser une lecture pas groupe de caractères de longueur variable, il me semble.
    Existerait-il une fonction 'read(...)' effectuant un 'parsing' de deux caractères
    - '-1' pour la fin du fichier
    - mais aussi un caractère au choix : '\n' dans mon cas ... très général, il me semble.

    2) A présent, j'ai programmé un algoritme de lecture par tampons de 23 octets fixes de longueur. A l'aide de
    System.out.println(((ByteBuffer)(tamponLect.flip())).asCharBuffer().toString());
    , je vois apparaître les caractères dans la fenêtre 'Output' de mon IDE NetBeans. Il n'apparaît que des symboles japonais ou chinois. Que faire pour obtenir les caractères ASCII ?

    Merci d'avance pour votre aide.
    Utile pour beaucoup d'entre nous, pas vrai ?

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonjour,

    Je pense que tu n'as pas compris la philosophie de Java. En Java on ne s'occupe pas de l'allocation mémoire, donc pas de malloc ou autres... Les chaines de longueurs variables c'est pas un problème en Java !

    Pour lire un fichier CSV je te conseil de passer par une bibliothèque externe. Deux articles sont dispos ici :
    http://thierry-leriche-dessirier.dev...ier-csv-5-min/
    http://thierry-leriche-dessirier.dev...csv-avec-java/

    Si tu n'es pas familier avec Java et qu'ajouter une librairie externe à ton projet te parait compliqué tu peux utiliser ce bout de code :
    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
      public List<String[]> lireFichierCSV(String nomFichier, String separateurChamp) throws FileNotFoundException {
        List<String[]> contenuFichierCSV = new ArrayList<String[]>();
     
        File fichierCsv = new File(nomFichier);
        Scanner scanner = new Scanner(fichierCsv);
        while (scanner.hasNext()) {
          String ligne = scanner.nextLine();
          String[] cellules = ligne.split(separateurChamp);
     
          contenuFichierCSV.add(cellules);
        }
        scanner.close();
     
        return contenuFichierCSV;
      }
    Attention ce bout de code est très sommaire. Si jamais tes champs contiennent le séparateur de champ ça ne fonctionnera pas.

    Ensuite tu peux utiliser la fonction comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    List<String[]> lignesCSV = lireFichierCSV("monFichier.csv",";");
    for(String[] cellules : lignesCSV){
        String champ1 = cellules[0];
        String champ2 = cellules[1];
     
        // remplir ta table swing ici
    }
    Bon courage,
    Romain.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Merci Romain pour ta réponse ... bien efficace.
    J'ai lu le document http://thierry-leriche-dessirier.dev...ec-java/#L16-C de Thierry Leriche-Dessirier. Vraiment à recommander. Enfin compréhensible.
    J'en ai implémenté les classes et j'arrive à obtenir un objet de type-classe CsvFile dont getData() retourne un objet de type List<String[]>.
    Pourrais-tu m'indiquer les instructions à rechercher pour que je puisse convertir cet objet de type List<String[]> en un objet de type Object[][] que nécessite MonModèleDeTable pour que mon tableau affiche toutes les données de mon fichier CSV ?
    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
        class MonModèleDeTable extends AbstractTableModel
        {   // Déclarations de variables
            private String[] nomsColonnes = {"Instant", "Puiss"};
            private Object[][] donnéesDEntrée = csvFile.getData();
    /*        {   
                 {"1/01/2013  00:00:00", "46.5"},
                 {"1/01/2013  00:15:00", "47.52"},
                 {"1/01/2013  00:30:00", "46.5"},
                 {"1/01/2013  00:45:00", "46.42"},
                 {"1/01/2013  01:00:00", "46.42"},
                 {"1/01/2013  01:15:00", "45"},
                 {"1/01/2013  01:30:00", "43"},
                 {"1/01/2013  01:45:00", "42.5"},
                 {"1/01/2013  02:00:00", "69"}
     */
            };
    Merci d'avance. Je n'oublierai pas aussi tôt que possible la mention "Résolu".

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonjour,

    Tu peux faire comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     public Object[][] convertirLignes(List<String[]> lignes) {
        // 2 correspond au nombre de colonne de ton fichier csv
        return lignes.toArray(new Object[lignes.size()][2]);
      }
    Romain.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Merci bien, Romain.
    Ca, maintenant !
    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2
    at choixpuissmachcogén.FichierDonnéesDEntrée$MonModèleDeTable.getValueAt(FichierDonnéesDEntrée.java:308)
    at javax.swing.JTable.getValueAt(JTable.java:2716)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MonModèleDeTable extends AbstractTableModel
        {   // Déclarations de variables
            private String[] nomsColonnes = {"Instant", "Puiss."};
            private List<String[]> données = csvFile2.getData();
            private Object[][] donnéesDEntrée = données.toArray(new Object[données.size()][2]);
            // Fin des déclarations de variables
     
            @Override public Object getValueAt(int row, int col)
            {   return donnéesDEntrée[row][col];
            }

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonjour,

    En informatique le premier élément d'un tableau se trouve toujours à l'index 0.

    Donc pour accéder à la première ligne et la première cellule de ton tableau c'est :
    Deuxième ligne, deuxième colonne :
    ------------
    | 0,0 | 0,1 |
    ------------
    | 1,0 | 1,1 |
    ------------
    | 2,0 | 2,1 |
    ------------
    ...

    Romain.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Bonjour Romain.
    Merci pour ta dernière réponse, mais qui cette fois - sauf le respect que je te dois - répond à côté et suppose un peu vite que je ne connais même pas les bases des prémices du beaba de Java : adressage d'Arrays multi-dimensionnelles.

    Bonjour les autres aussi.
    Dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lignes.toArray(new Object[lignes.size()][2]);
    , c'est 'lignes.size()' qui cause
    java.lang.ArrayIndexOutOfBoundsException: 2
    Même en remplaçant 'lignes.size()' par le chiffre 5, l'erreur se produit. (Et 'lignes.size()' varie autour de 35144 dans mon application.)

    Je vais réviser l'application de 'toArray()' à 'List<String[]>' (qui est le type de 'lignes' ou 'données') et comment remplir correctement un objet de classe JTable avec une List<String[]> ou List<String>.

    N.B.: De l'excellente mais volumineuse explication de Thierry Leriche-Dessirier(http://thierry-leriche-dessirier.dev...ec-java/#L16-C), j'ai implémenté les DAO's (CsvChienDao1 = PuissancesDAO et SimpleChien = Puissance) avec leurs interfaces respectifs (ChienDAO = PuissancesDAO_I et Chien = Puissance_I).

    Merci d'avance à ceux qui persévèrent à vouloir m'aider. Si je trouve l'erreur, je vous l'indiquerai.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonjour,

    L'erreur que tu m'as montrée était :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2
    at choixpuissmachcogén.FichierDonnéesDEntrée$MonModèleDeTable.getValueAt(FichierDonnéesDEntrée.java:308)
    at javax.swing.JTable.getValueAt(JTable.java:2716)
    La ligne que j'ai affichée en rouge te donne le lieu de l'erreur. Tu peux aisément voir que le ArrayIndexOutOfBoundsException a eu lieu lors de l'appel à la méthode "getValueAt" dans la classe FichierDonnéesDEntrée à la ligne 308.

    Je persiste donc à dire que ton erreur est que tu fais dans ton code des "getValueAt(xx,2)" au lieux de faire des "getValueAt(xx,0)" pour obtenir les valeurs de la première colonne et getValueAt(xx,1) pour obtenir les valeurs de la deuxième colonne.

    D'autre par je peux te garantir que cette ligne ne te donnera jamais un ArrayIndexOutOfBoundsException :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lignes.toArray(new Object[lignes.size()][2]);
    ArrayIndexOutOfBoundsException signifie que tu as accédé à une cellule d'un tableau qui est en dehors de ses limites. Lors que tu fais "new Object[lignes.size()][2]" tu n'accèdes pas à une cellules d'un tableau, tu crées le tableau, et tu es bien libre de le créer à la taille que tu veux.

    Même en remplaçant 'lignes.size()' par le chiffre 5, l'erreur se produit. (Et 'lignes.size()' varie autour de 35144 dans mon application.)
    Pas étonnant, comme je te le dis l'erreur ne vient pas de là, tu peux trifouiller ce que tu veux ici, ça ne changera rien à l'erreur

    Romain.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Cher Romain,
    Tu as tout à fait raison. En fait, je déclarais un tableau à 3 colonnes ('nomColonnes' à 3 en-têtes + 'donnéesDEntrée' à 3 chaînes de caract. par ligne), prévoyant que plus tard, l'application allait remplir la 3e colonne dynamiquement. Mais j'omettais la déclaration d'un 3e champs dans mon objet de type 'Puissance' (= une ligne de données) et sa surtout fonction 'getValueAt(r,c)'.
    Le constructeur de la table ne l'omettait bien sûr pas, lorsque je programmais que 'donnéesDEntrée' devait puiser les données d'un fichier CSV (List<String[]> soit 2 champs par ligne) plutôt que d'un petit array à deux dimensions d'essai (3 chaînes de car. par ligne) instancié dans la classe.
    J'ai naturellement pensé que comme chaque ligne de la liste 'List<String[]>' (composée à partir du fichier CSV) ne comporte que deux champs (2 ch. d car. = un objet de type 'Puissance'), la variable 'col' pour les fonctions l'utilisant en paramètre d'entrée allait s'arrêter à 1 (au 2e champs).
    Mais je ne trouve dans aucune documentation que c'est la dimension de l'array de noms des colonnes qui détermine la variable 'nombre de colonnes' que toutes les fonctions de la classe 'AbstractTableModel' emploient comme limite. Penses-tu pouvoir le confirmer ? Y aurait-il moyen de modifier cette limite ?

    Essai : Je viens de retirer le 3e champs de l'array 'nomsColonnes'. Je n'ai donc plus que deux colonnes, comme le nombre de champs de chaque ligne de mon fichier CSV. Pourtant, à l'exécution
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
    at java.util.Vector.elementAt(Vector.java:470)
    at javax.swing.table.DefaultTableColumnModel.getColumn(DefaultTableColumnModel.java:294)
    at choixpuissmachcogén.donnéesDEntrée.FichierDonnéesDEntrée.initGuiComponents(FichierDonnéesDEntrée.java:164)
    Ce n'est donc quand même pas le nombre de champs d'en-têtes de colonnes qui détermine la limite de comptage des colonnes pour les fonctions de AbstractTableModel ...

    2e essai : J'ai aussi changé le Object[][] par un List<Puissance> dont Puissance contient seul.t 2 ch.d car.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
            private List<Puissance> donnéesDEntrée;
            donnéesDEntrée = new ArrayList<Puissance>();
            donnéesDEntrée.add(new Puissance("Instant", "2013 KW"));
            donnéesDEntrée.add(new Puissance("1/01/2013  00:00:00", "46.5"));
            donnéesDEntrée.add(new Puissance("1/01/2013  00:15:00", "47.52"));
            donnéesDEntrée.add(new Puissance("1/01/2013  00:30:00", "46.5"));
            donnéesDEntrée.add(new Puissance("1/01/2013  00:45:00", "46.42"));
            donnéesDEntrée.add(new Puissance("1/01/2013  01:00:00", "46.42"));
            donnéesDEntrée.add(new Puissance("1/01/2013  01:15:00", "45"));
            donnéesDEntrée.add(new Puissance("1/01/2013  01:30:00", "43"));
            donnéesDEntrée.add(new Puissance("1/01/2013  01:45:00", "42.5"));
            donnéesDEntrée.add(new Puissance("1/01/2013  02:00:00", "69"));
    Brrrrrr

    Grand merci, Romain.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Romain,
    Ne te casse plus la tête pour moi. J'ai trouvé : J'ai supprimé la troisième colonne aussi au niveau de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            TableColumn column;
                column = table.getColumnModel().getColumn(0);
                column.setPreferredWidth(70);
                // column.setBackgroundColor();   N'existe pas
                column = table.getColumnModel().getColumn(1);
                column.setPreferredWidth(20);
    //            column = table.getColumnModel().getColumn(2);
    //            column.setPreferredWidth(20);
    J'ai donc éliminé 'getColumnModel().getColumn(2)' et tout va bien. Je ne l'ai vu qu'après m'être détendu avec une bierre de mon coin, couronnée "meilleure bierre du monde" à N-Y, comme l'an passé aussi : une West-Vleteren de 12%. Je t'en enverrais bien au moins une bouteille, mais ...

    A retenir : On ne peut pas créer un tableau à 3 colonnes en n'important les données que des deux premières.
    Mes excuses et mes remerciements pour ta patience.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [awk] Sous-chaîne de longueur variable
    Par David_LeNovis dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 14/11/2013, 13h49
  2. lecture de lignes de longueurs variables
    Par moon61 dans le forum C
    Réponses: 14
    Dernier message: 09/04/2009, 10h13
  3. Tableau de chaînes de longueur variable
    Par alband85 dans le forum C#
    Réponses: 3
    Dernier message: 20/08/2007, 09h49
  4. Réponses: 1
    Dernier message: 30/04/2007, 15h33
  5. Réponses: 3
    Dernier message: 14/04/2006, 09h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo