Mon csv est lu dans le fichier System.out, mais j’ai remarqué que tout texte avec un espace était déplacé dans la ligne suivante (en tant que retour\n)
Voici comment mon csv commence:
first,last,email,address 1, address 2
john,smith,[email protected],123 St. Street,
Jane,Smith,[email protected],4455 Roger Cir,apt 2
Après avoir exécuté mon application, toute cellule avec un espace (adresse 1) est projetée sur la ligne suivante.
import Java.io.File;
import Java.io.FileNotFoundException;
import Java.util.Scanner;
public class main {
public static void main(String[] args) {
// -define .csv file in app
String fileNameDefined = "uploadedcsv/employees.csv";
// -File class needed to turn stringName to actual file
File file = new File(fileNameDefined);
try{
// -read from filePooped with Scanner class
Scanner inputStream = new Scanner(file);
// hashNext() loops line-by-line
while(inputStream.hasNext()){
//read single line, put in string
String data = inputStream.next();
System.out.println(data + "***");
}
// after loop, close scanner
inputStream.close();
}catch (FileNotFoundException e){
e.printStackTrace();
}
}
}
Alors voici le résultat dans la console:
premier, dernier, email, adresse 1, adresse 2 john, smith, blah @ blah.com, 123 St. Street, Jane, Smith, blech @ blech.com, 4455 Roger Cir, apt 2
Est-ce que j'utilise mal le scanner?
scanner.useDelimiter(",");
Cela devrait marcher.
import Java.io.File;
import Java.io.FileNotFoundException;
import Java.util.Scanner;
public class TestScanner {
public static void main(String[] args) throws FileNotFoundException {
Scanner scanner = new Scanner(new File("/Users/pankaj/abc.csv"));
scanner.useDelimiter(",");
while(scanner.hasNext()){
System.out.print(scanner.next()+"|");
}
scanner.close();
}
}
Pour le fichier CSV:
a,b,c d,e
1,2,3 4,5
X,Y,Z A,B
La sortie est:
a|b|c d|e
1|2|3 4|5
X|Y|Z A|B|
Veuillez arrêter d'écrire des analyseurs syntaxiques CSV défectueux!
J'ai vu des centaines de parseurs CSV et ce qu'on appelle tutorials pour eux en ligne.
Presque chacun d'entre eux se trompe!
Cela ne serait pas une si mauvaise chose car cela ne me concerne pas, mais ceux qui essaient d'écrire CSV lecteurs et se trompent ont tendance à écrire CSV écrivains aussi. Et comprenez-les aussi. Et ceux-ci, je dois écrire des analyseurs syntaxiques.
S'il vous plaît gardez à l'esprit que CSV (dans l'ordre croissant pas si évident):
"foo","","bar"
ou non: "foo",,"bar"
Frodo's Ring
sera 'Frodo''s Ring'
"foo""", """bar", """"
)Si vous pensez que ce n'est pas un problème évident, alors détrompez-vous. J'ai vu chacun des de ces éléments mal implémentés. Même dans les principaux progiciels. (par exemple, suites bureautiques, systèmes CRM)
Il existe de bons lecteurs et rédacteurs CSV prêts à l'emploi qui fonctionnent correctement:
Si vous insistez pour écrire vous-même, lisez au moins le (très court) RFC for CSV .
Scanner.next()
ne lit pas de nouvelle ligne mais lit le prochain jeton, délimité par un espace (par défaut, si useDelimiter()
n'a pas été utilisé pour changer le motif de délimiteur) Pour lire une ligne, utilisez Scanner.nextLine()
.
Une fois que vous avez lu une seule ligne, vous pouvez utiliser String.split(",")
pour séparer la ligne en champs. Cela permet d'identifier les lignes qui ne comprennent pas le nombre de champs requis. Utiliser useDelimiter(",");
ignorerait la structure du fichier basée sur les lignes (chaque ligne consiste en une liste de champs séparés par une virgule). Par exemple:
while (inputStream.hasNextLine())
{
String line = inputStream.nextLine();
String[] fields = line.split(",");
if (fields.length >= 4) // At least one address specified.
{
for (String field: fields) System.out.print(field + "|");
System.out.println();
}
else
{
System.err.println("Invalid record: " + line);
}
}
Comme déjà mentionné, l'utilisation d'une bibliothèque CSV est recommandée. D'une part, cela (et la solution useDelimiter(",")
) ne gérera pas correctement les identificateurs entre guillemets contenant des caractères ,
.
Je suis d'accord avec Scheintod pour dire que l'utilisation d'une bibliothèque CSV existante est une bonne idée d'avoir la conformité à la RFC-4180 dès le début. Outre OpenCSV et Oster Miller, il existe une série d'autres bibliothèques CSV. Si les performances vous intéressent, vous pouvez jeter un oeil à uniVocity/csv-parsers-compare . Cela montre que
sont systématiquement les plus rapides en utilisant JDK 6, 7, 8 ou 9. L’étude n’a révélé aucun problème de compatibilité RFC 4180 dans l’un de ces trois problèmes. OpenCSV et Oster Miller sont environ deux fois plus lents que ceux-ci.
Je ne suis en aucun cas associé au (x) auteur (s), mais en ce qui concerne l’analyseur uniVocity CSV, l’étude peut être biaisée car son auteur est identique à celui de cet analyseur.
À noter, l'auteur de SimpleFlatMapper a également publié un performance performance comparant seulement ces trois.
Fractionnez nextLine () par ce délimiteur: (?=([^\"]*\"[^\"]*\")*[^\"]*$)")
.