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

Java Discussion :

regex CSV avec des guillemets


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de thierryler
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 078
    Par défaut regex CSV avec des guillemets
    Bonjour,

    J'ai un fichier csv, avec mes valeurs séparées par des virgules. Quand les champs contiennent des virgules, ils sont encapsulés par des guillemets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    # une ligne exemple
    "Maman","Papa","Julie, Franck et Tom","Mamy","Papy"
    Dans mon exemple la 3ème colonne, avec "Julie, Franck et Tom" contient le séparateur.

    Du coup, je ne sais pas trop comment faire mon regex pour le slit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    String line <== "Maman","Papa","Julie, Franck et Tom","Mamy","Papy"
     
    String regex = "???"
     
    String[] values = line.split(regex)
    Bon je suis trop mauvais en regex alors excusez moi par avance si c'est trop simple...
    Thierry Leriche-Dessirier
    Consultant Java JEE Web Agile freelance
    Rédacteur pour Developpez
    Professeur de Génie Logiciel à l'ESIEA

    Site : http://www.icauda.com / Linked'in : http://www.linkedin.com/in/thierryler / Twitter : @ThierryLeriche

  2. #2
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Salut,

    Pour le meme genre de probleme, je suis passé par un parse par programme. Parce qu'il ne faut pas oublier qu'un champ peut contenir un '\n' (et donc un getLine ne suffit pas)...

    Pour les regex, désolé mais c'est pas mon truc non plus

  3. #3
    Rédacteur/Modérateur
    Avatar de Logan Mauzaize
    Homme Profil pro
    Architecte technique
    Inscrit en
    Août 2005
    Messages
    2 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : Transports

    Informations forums :
    Inscription : Août 2005
    Messages : 2 894
    Par défaut
    Je ne sais pas trop si c'est possible d'utiliser une expression régulière pour ça.

    J'ai plutôt l'habitude pour traiter ce genre de chaîne d'utiliser des "modes".
    Le principe dans ton cas :
    Je cherche le premier caractère spécial le guillemet ou la virgule.
    Si c'est un guillemet et que je suis en mode "Guillemet ouvert" (un petit booléen fait l'affaire), je passe en mode "guillemet fermé".
    Si c'est un guillemet et que je suis en mode "Guillemet fermé", je passe en mode "guillemet ouvert".
    Si c'est une virgule et que je suis en mode "Guillemet ouvert", j'ignore la virgule.
    Si c'est une virgule et que je suis en mode "Guillemet fermé", c'est la fin de la valeur.

    Il reste à vérifier quelques points:
    • L'ouverture d'un guillemet n'est valable qu'en début de valeur.
    • La fin du mode "Guillemet fermé" implique que le caractère suivant est une virgule.
    • Il faut traiter le cas où la valeur contient un saut de ligne
    • Il faut traiter le cas où la valeur contient un guillemet et un saut de ligne
    • Il faut traiter le cas où la valeur contient un guillemet et une virgule
    Java : Cours et tutoriels - FAQ - Java SE 8 API - Programmation concurrente
    Ceylon : Installation - Concepts de base - Typage - Appels et arguments

    ECM = Exemple(reproduit le problème) Complet (code compilable) Minimal (ne postez pas votre application !)
    Une solution vous convient ? N'oubliez pas le tag
    Signature par pitipoisson

  4. #4
    Membre expérimenté
    Inscrit en
    Mai 2007
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 335
    Par défaut
    Bonjour,
    pas si simple en fait, puisque la détection de virgule dépend du contexte, on est à la limite de la regexp et de l'analyse BNF non ?

    bref, plutôt qu'un split, je passerais par un Matcher en bouclant sur des find/group ,on matche un groupe et on traite sa valeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
     Pattern p = Pattern.compile("\"([^\"]*)\"([^,]*),");
     Matcher m = p.matcher("aaaaab");//la Ligne à matcher
    while(m.find){
      String s1 = m.group(1);//contient les chaines avec guillemets
      String s2 = m.group(2);//contient les chaines sans guillemets
      String s=s1;
      if(s1.length() == 0) s=s2
      ...traiter s...
    }
    il y a surement plus efficient comme regexp... mais ça devrais marcher.

    Edit: (petite modif sur la regexp.)
    oubli: il faudrait matcher la fin de ligne avec "\"([^\"]*)\"([^,]*)$" par exemple.

    Il y eu plein de réponse pendant que j'écrivais Donc pour la remarque du multi-ligne, c'est clair qu'une regexp ne peut pas être multi-ligne.

  5. #5
    Membre chevronné
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2010
    Messages
    158
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Octobre 2010
    Messages : 158
    Par défaut
    J'avais déjà essayé de composer une regex utilisable sur du CSV.
    Je ne sais pas si ça te conviendra, mais tu peux toujours aller voir ce message.

  6. #6
    Rédacteur
    Avatar de thierryler
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 078
    Par défaut
    En fait, dans un premier temps, je voudrais juste des valeurs sur une seule ligne.

    Mais je peux avoir les séparateurs suivants :
    * virgule ou
    * point-virgule ou
    * barre ou
    * tab

    Par contre je n'utilise que les guillemets comme délimiteur.

    Dans un second temps, je vais avoir besoin de valeurs sur plusieurs lignes, donc je ne serai plus en mesure d'utiliser br.readLine()...
    Thierry Leriche-Dessirier
    Consultant Java JEE Web Agile freelance
    Rédacteur pour Developpez
    Professeur de Génie Logiciel à l'ESIEA

    Site : http://www.icauda.com / Linked'in : http://www.linkedin.com/in/thierryler / Twitter : @ThierryLeriche

  7. #7
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Cadeau
    Ca renvoie un tableau de String (chacune correspondant à une cellule)

    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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
          public static String[] splitNextLigneCsv(StreamReader srFichier)
          {
             String[] ret = null;
             List<String> listCells = new List<String>();
             System.Text.StringBuilder ligne = new System.Text.StringBuilder(1024);
     
             bool isOpen = false;
             int n = srFichier.Read();
             bool shouldContinue = true;
             while ((n != -1) &&
                (shouldContinue != false))
             {
                char c = (char)n;
                if (c == '"')
                {
                   if (ligne.Length == 0)
                   {
                      // C'est le premier guillement, on l'ignore
                      isOpen = true;
                      n = srFichier.Read();
                   }
                   else
                   {
                      // On lit le prochain caractere. Si c'est un ';'
                      // un retour chariot ou la fin du fichier, on l'ignore
                      n = srFichier.Read();
                      if (n != -1)
                      {
                         if (((char)n != ';') &&
                            ((char)n != '\n') &&
                            ((char)n != '\r'))
                         {
                            ligne.Append(c);
                         }
                         else
                         {
                            //Fin de la cellule
                            isOpen = false;
                         }
                      }
                      else
                      {
                         //Fin de la cellule et du fichier
                         listCells.Add(ligne.ToString());
                         ligne.Clear();
                         shouldContinue = false;
                      }
                   }
                }
                else if ((c == ';') ||
                   (c == '\r') ||
                   (c == '\n'))
                {
                   if (isOpen == false)
                   {
                      //Fin de la cellule
                      if (c == ';')
                      {
                         listCells.Add(ligne.ToString());
                         ligne.Clear();
                      }
                      else if (listCells.Count > 0)
                      {
                         listCells.Add(ligne.ToString());
                         ligne.Clear();
                         shouldContinue = false;
                      }
     
                   }
                   else
                   {
                      ligne.Append(c);
                   }
                   n = srFichier.Read();
                }
                else
                {
                   ligne.Append(c);
                   n = srFichier.Read();
                }
             }
     
             if (listCells.Count > 0)
             {
                ret = listCells.ToArray();
             }
     
             return ret;
          }

  8. #8
    Rédacteur
    Avatar de thierryler
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    4 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 078
    Par défaut
    heu y a plein de classes inconnues...
    Thierry Leriche-Dessirier
    Consultant Java JEE Web Agile freelance
    Rédacteur pour Developpez
    Professeur de Génie Logiciel à l'ESIEA

    Site : http://www.icauda.com / Linked'in : http://www.linkedin.com/in/thierryler / Twitter : @ThierryLeriche

Discussions similaires

  1. [XL-2010] Convertir plusieurs fichiers excel en csv avec des guillemets
    Par karido-74 dans le forum Macros et VBA Excel
    Réponses: 41
    Dernier message: 29/01/2014, 18h32
  2. [CSV] importation CSV avec des guillemets
    Par trash_board dans le forum Langage
    Réponses: 3
    Dernier message: 12/09/2006, 14h08
  3. Réponses: 9
    Dernier message: 28/10/2005, 11h43
  4. [C#] Prob IndexOf sous Pocket Pc avec des guillemets
    Par freddyboy dans le forum Windows Mobile
    Réponses: 7
    Dernier message: 10/06/2004, 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