web-dev-qa-db-fra.com

Analyse CSV dans Java - exemple de travail ..?

Je veux écrire un programme pour une école Java projet pour analyser certains CSV que je ne connais pas. Je connais le type de données de chaque colonne - bien que je ne connaisse pas le délimiteur.

Le problème que je ne sais même pas comment résoudre, c'est d'analyser les colonnes Date ou même DateTime. Ils peuvent être dans l'un des nombreux formats.

J'ai trouvé de nombreuses bibliothèques mais je n'ai aucune idée de ce qui convient le mieux à mes besoins: http://opencsv.sourceforge.net/http://www.csvreader.com/Java_csv.phphttp://supercsv.sourceforge.net/http://flatpack.sourceforge.net/

Le problème est que je suis un débutant Java débutant. Je crains qu'aucune de ces bibliothèques ne puisse faire ce dont j'ai besoin ou que je ne puisse pas les convaincre de le faire.

Je parie qu'il y a beaucoup de gens ici qui ont un exemple de code qui pourrait me permettre de démarrer en un rien de temps pour ce dont j'ai besoin:

  • se divise automatiquement en colonnes (délimiteur inconnu, les types de colonnes sont connus)
  • cast en Columntype (devrait faire face à $,%, etc.)
  • convertir des dates en Java objets de date ou de calendrier

Ce serait bien d'obtenir autant d'échantillons de code que possible par e-mail.

Merci beaucoup! COMME

17
Andy Schmidt

Il y a un sérieux problème avec l'utilisation

String[] strArr=line.split(",");

afin d'analyser les fichiers CSV, et c'est parce qu'il peut y avoir des virgules dans les valeurs de données, et dans ce cas, vous devez les citer, et ignorer les virgules entre guillemets.

Il existe un moyen très très simple d'analyser ceci:

/**
* returns a row of values as a list
* returns null if you are past the end of the input stream
*/
public static List<String> parseLine(Reader r) throws Exception {
    int ch = r.read();
    while (ch == '\r') {
        //ignore linefeed chars wherever, particularly just before end of file
        ch = r.read();
    }
    if (ch<0) {
        return null;
    }
    Vector<String> store = new Vector<String>();
    StringBuffer curVal = new StringBuffer();
    boolean inquotes = false;
    boolean started = false;
    while (ch>=0) {
        if (inquotes) {
            started=true;
            if (ch == '\"') {
                inquotes = false;
            }
            else {
                curVal.append((char)ch);
            }
        }
        else {
            if (ch == '\"') {
                inquotes = true;
                if (started) {
                    // if this is the second quote in a value, add a quote
                    // this is for the double quote in the middle of a value
                    curVal.append('\"');
                }
            }
            else if (ch == ',') {
                store.add(curVal.toString());
                curVal = new StringBuffer();
                started = false;
            }
            else if (ch == '\r') {
                //ignore LF characters
            }
            else if (ch == '\n') {
                //end of a line, break out
                break;
            }
            else {
                curVal.append((char)ch);
            }
        }
        ch = r.read();
    }
    store.add(curVal.toString());
    return store;
}

Cette approche présente de nombreux avantages. Notez que chaque caractère est touché EXACTEMENT une fois. Il n'y a pas de lecture en avant, de repoussage dans le tampon, etc. Pas de recherche en avant jusqu'à la fin de la ligne, puis de copier la ligne avant l'analyse. Cet analyseur fonctionne uniquement à partir du flux et crée chaque valeur de chaîne une fois. Cela fonctionne sur les lignes d'en-tête et les lignes de données, il vous suffit de traiter la liste renvoyée appropriée à cela. Vous lui donnez un lecteur, donc le flux sous-jacent a été converti en caractères en utilisant l'encodage que vous choisissez. Le flux peut provenir de n'importe quelle source: un fichier, une publication HTTP, un get HTTP et vous analysez le flux directement. Il s'agit d'une méthode statique, il n'y a donc aucun objet à créer et à configurer, et lorsque cela revient, il n'y a plus de mémoire.

Vous pouvez trouver une discussion complète de ce code, et pourquoi cette approche est préférée dans mon article de blog sur le sujet: La seule classe dont vous avez besoin pour les fichiers CSV .

18
AgilePro

Vous avez également la bibliothèque Apache Commons CSV , peut-être qu'elle fait ce dont vous avez besoin. Voir le guide . Mise à jour vers la version 1.1 en 2014-11.

De plus, pour l'édition infaillible, je pense que vous devrez le coder vous-même ... à travers SimpleDateFormat vous pouvez choisir vos formats et spécifier différents types, si le Date ne ressemble à aucun de vos types prédéfinis, ce n'est pas une date.

18
Valentin Rocher

Mon approche serait pas de commencer par écrire votre propre API. La vie est trop courte et il y a des problèmes plus urgents à résoudre. Dans cette situation, je typiquement:

  • Trouvez une bibliothèque qui semble faire ce que je veux. S'il n'en existe pas, alors implémentez-le.
  • Si une bibliothèque existe, mais je ne suis pas sûr qu'elle conviendra à mes besoins, écrivez une API d'adaptateur léger autour d'elle, afin que je puisse contrôler comment elle s'appelle. L'API d'adaptateur exprime l'API I besoin, et elle mappe ces appels à l'API sous-jacente.
  • Si la bibliothèque ne s'avère pas appropriée, je peux en échanger une autre sous l'API de l'adaptateur (que ce soit une autre source ouverte ou quelque chose que j'écris moi-même) avec un minimum d'effort, sans affecter les appelants.

Commencez avec quelque chose que quelqu'un a déjà écrit. Les chances sont que ça fera ce que vous voulez. Vous pouvez toujours écrire le vôtre plus tard, si nécessaire. OpenCSV est un aussi bon point de départ que n'importe quel autre.

7
Brian Clapper

Vous voudrez peut-être jeter un œil à cette spécification pour CSV. Gardez à l'esprit qu'il n'existe aucune spécification officielle reconnue.

Si vous n'avez pas maintenant le délimiteur, il ne sera pas possible de le faire, vous devez donc le découvrir d'une manière ou d'une autre. Si vous pouvez effectuer une inspection manuelle du fichier, vous devriez rapidement pouvoir voir de quoi il s'agit et coder en dur dans votre programme. Si le délimiteur peut varier, votre seul espoir est de pouvoir le déduire de la mise en forme des données connues. Lorsque Excel importe des fichiers CSV, il permet à l'utilisateur de choisir le délimiteur et c'est une solution que vous pouvez également utiliser.

2

j'ai dû utiliser un analyseur csv il y a environ 5 ans. semble qu'il existe au moins deux normes csv: http://en.wikipedia.org/wiki/Comma-separated_values et ce que Microsoft fait dans Excel.

j'ai trouvé ce libaray qui mange à la fois: http://ostermiller.org/utils/CSV.html , mais afaik, il n'a aucun moyen de déduire de quel type de données étaient les colonnes.

2
Ray Tayek

Je suis d'accord avec @Brian Clapper. J'ai utilisé SuperCSV comme analyseur bien que j'aie eu des résultats mitigés. J'apprécie la polyvalence de celui-ci, mais il y a des situations dans mes propres fichiers csv pour lesquelles je n'ai pas pu réconcilier "encore". J'ai confiance en ce produit et je le recommanderais dans l'ensemble - il me manque quelque chose de simple, sans aucun doute, que je fais dans ma propre mise en œuvre.

SuperCSV peut analyser les colonnes dans différents formats, effectuer des modifications sur les colonnes, etc. Cela vaut la peine d'y jeter un œil. Il contient également des exemples et est facile à suivre.

La seule/unique limitation que j'ai est d'attraper une colonne `` vide '' et de l'analyser en entier ou peut-être en blanc, etc. Donc, je me blâme d'abord, pour l'instant. :-)

Quoi qu'il en soit, jetez un œil à SuperCSV. http://supercsv.sourceforge.net/

1
Davidson

Je vous recommande de commencer par séparer votre tâche en ses composants.

  1. Lire les données de chaîne à partir d'un CSV
  2. Convertir les données de chaîne au format approprié

Une fois que vous avez fait cela, il devrait être assez simple d'utiliser l'une des bibliothèques auxquelles vous vous connectez (qui gérera certainement la tâche # 1). Ensuite, parcourez les valeurs renvoyées et convertissez/convertissez chaque valeur de chaîne en la valeur souhaitée.

Si la question est de savoir comment convertir des chaînes en différents objets, cela dépendra du format avec lequel vous commencez et du format avec lequel vous souhaitez vous retrouver.

DateFormat.parse (), par exemple, analysera les dates des chaînes. Voir SimpleDateFormat pour construire rapidement un DateFormat pour une certaine représentation de chaîne. Integer.parseInt () supprimera les entiers des chaînes.

Devise, vous devrez décider comment vous voulez la capturer. Si vous souhaitez simplement capturer comme un flottant, alors Float.parseFloat () fera l'affaire (utilisez simplement String.replace () pour supprimer tous les $ et virgules avant de l'analyser). Ou vous pouvez analyser dans un BigDecimal (afin que vous n'ayez pas de problèmes d'arrondi). Il peut y avoir une meilleure classe pour le traitement des devises (je ne fais pas beaucoup de cela, donc je ne connais pas ce domaine du JDK).

0
Kevin Day

Fondamentalement, vous devrez lire le fichier ligne par ligne.

Ensuite, vous devrez diviser chaque ligne par le délimiteur, par exemple une virgule (CSV signifie valeurs séparées par des virgules), avec

String[] strArr=line.split(",");

Cela le transformera en un tableau de chaînes que vous pourrez ensuite manipuler, par exemple avec

String name=strArr[0];
int yearOfBirth = Integer.valueOf(strArr[1]);
int monthOfBirth = Integer.valueOf(strArr[2]);
int dayOfBirth = Integer.valueOf(strArr[3]);
GregorianCalendar dob=new GregorianCalendar(yearOfBirth, monthOfBirth, dayOfBirth);
Student student=new Student(name, dob); //lets pretend you are creating instances of Student

Vous devrez le faire pour chaque ligne, donc encapsulez ce code dans une boucle while. (Si vous ne connaissez pas le délimiteur, ouvrez simplement le fichier dans un éditeur de texte.)

0

Écrire votre propre analyseur est amusant, mais vous devriez probablement jeter un œil à Open CSV . Il offre de nombreuses façons d'accéder au CSV et permet également de générer du CSV. Et il gère correctement les échappements. Comme mentionné dans un autre article, il existe également une bibliothèque d'analyse CSV dans Apache Commons, mais celle-ci n'est pas encore publiée.

0
Ichthyo

Vous devrez au moins connaître le délimiteur de colonne.

0
Richard West