J'ai une chaîne délimitée par des tabulations (représentant une table) qui est passée à ma méthode. Lorsque je l'imprime sur la ligne de commande, il apparaît comme un tableau avec des lignes:
http://i.stack.imgur.com/2fAyq.gif
La fenêtre de commande est correctement tamponnée. Je pense qu'il y a définitivement un nouveau caractère de ligne avant ou après chaque ligne.
Mon problème est que je souhaite diviser la chaîne entrante en chaînes individuelles représentant les lignes de la table. Jusqu'à présent, j'ai:
private static final String newLine = System.getProperty("line.separator").toString();
private static final String tab = "\t";
private static String[] rows;
...
rows = tabDelimitedTable.split(newLine); //problem is here
System.out.println();
System.out.println("################### start debug ####################");
System.out.println((tabDelimitedTable.contains(newLine)) ? "True" : "False");
System.out.println("#################### end debug###################");
System.out.println();
sortie:
################### start debug ####################
False
#################### end debug###################
Évidemment, il y a quelque chose dans la chaîne qui dit au système d'exploitation de commencer une nouvelle ligne. Pourtant, il ne contient apparemment aucun caractère de nouvelle ligne.
Exécution du dernier JDK sous Windows XP SP3.
Des idées?
Essayer
rows = tabDelimitedTable.split("[" + newLine + "]");
Cela devrait résoudre le problème regex.
De plus, ce n'est pas un type important mais de retour
System.getProperty("line.separator")
is String donc pas besoin d'appeler toString ().
Vous devez [~ # ~] pas [~ # ~] supposer qu'un fichier texte d'entrée arbitraire utilise le "correct" spécifique à la plate-forme newline séparateur. Cela semble être la source de votre problème; cela a peu à voir avec l'expression régulière.
Pour illustrer, sur la plate-forme Windows, System.getProperty("line.separator")
est "\r\n"
(CR + LF). Cependant, lorsque vous exécutez votre Java sur cette plate-forme, vous devrez peut-être très bien gérer un fichier d'entrée dont le séparateur de ligne est simplement "\n"
(LF). Peut-être que ce fichier a été initialement créé sur la plate-forme Unix, puis transféré en mode binaire (au lieu de texte) vers Windows. Il peut exister de nombreux scénarios dans lesquels vous pouvez rencontrer ce type de situations, où vous devez analyser un fichier texte en entrée qui n'utilise pas le séparateur de nouvelle ligne de la plate-forme actuelle.
(Par coïncidence, lorsqu'un fichier texte Windows est transféré vers Unix en mode binaire, de nombreux éditeurs affichent ^M
, Ce qui déroute certaines personnes qui ne comprennent pas ce qui se passe).
Lorsque vous produisez un fichier texte en sortie, vous devriez probablement préférer le séparateur de nouvelle ligne spécifique à la plate-forme, mais lorsque vous êtes consommant un fichier texte en entrée, il n'est probablement pas sûr de supposer qu'il utilise correctement le séparateur de nouvelle ligne spécifique à la plate-forme.
Une façon de résoudre le problème consiste à utiliser par exemple Java.util.Scanner
. Il a une méthode nextLine()
qui peut renvoyer la ligne suivante (si elle existe), gérant correctement toute incohérence entre le séparateur de nouvelle ligne de la plate-forme et le fichier texte d'entrée.
Vous pouvez également combiner 2 Scanner
, un pour analyser le fichier ligne par ligne et un autre pour analyser les jetons de chaque ligne. Voici un exemple d'utilisation simple qui divise chaque ligne en List<String>
. L'ensemble du fichier devient donc un List<List<String>>
.
C'est probablement une meilleure approche que de lire le fichier entier dans un énorme String
puis split
en lignes (qui sont ensuite split
en parties).
String text
= "row1\tblah\tblah\tblah\n"
+ "row2\t1\t2\t3\t4\r\n"
+ "row3\tA\tB\tC\r"
+ "row4";
System.out.println(text);
// row1 blah blah blah
// row2 1 2 3 4
// row3 A B C
// row4
List<List<String>> input = new ArrayList<List<String>>();
Scanner sc = new Scanner(text);
while (sc.hasNextLine()) {
Scanner lineSc = new Scanner(sc.nextLine()).useDelimiter("\t");
List<String> line = new ArrayList<String>();
while (lineSc.hasNext()) {
line.add(lineSc.next());
}
input.add(line);
}
System.out.println(input);
// [[row1, blah, blah, blah], [row2, 1, 2, 3, 4], [row3, A, B, C], [row4]]
Java.util.Scanner
- a de nombreux exemples d'utilisationSous Windows, line.separator est une combinaison CR/LF (référence ici ).
La méthode Java String.split()
prend une expression régulière . Je pense donc qu'il y a une certaine confusion ici.
Essayez BufferedReader.readLine()
au lieu de toutes ces complications. Il reconnaîtra tous les terminateurs de ligne possibles.
Essaye ça:
rows = tabDelimitedTable.split("[\\r\\n]+");
Cela devrait fonctionner indépendamment des délimiteurs de ligne dans l'entrée et ignorera les lignes vides.
Je pense que votre problème est que String.split()
traite son argument comme une expression régulière, et les expressions régulières traitent spécialement les nouvelles lignes. Vous devrez peut-être créer explicitement un objet regex à passer à split()
(il y en a une autre surcharge) et configurer cette regex pour autoriser les sauts de ligne en passant MULTILINE
dans le paramètre flags de Pattern.compile()
. Documents
Les autres répondants ont raison de dire que split () prend une expression régulière comme argument, vous devrez donc le corriger en premier. L'autre problème est que vous supposez que les caractères de saut de ligne sont les mêmes que ceux par défaut du système. Selon d'où proviennent les données et où le programme s'exécute, cette hypothèse peut ne pas être correcte.