java - jdk - ¿Cómo uso System.getProperty("line.separator"). ToString()?
oracle java (7)
Tengo una cadena delimitada por tabulaciones (que representa una tabla) que se pasa a mi método. Cuando lo imprimo en la línea de comando, aparece como una tabla con filas:
http://i.stack.imgur.com/2fAyq.gif
La ventana de comando está correctamente almacenada. Mi pensamiento es que definitivamente hay un nuevo carácter de línea antes o después de cada fila.
Mi problema es que quiero dividir la cadena entrante en cadenas individuales que representan las filas de la tabla. Hasta ahora tengo:
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();
salida:
################### start debug ####################
False
#################### end debug###################
Obviamente hay algo en la cadena que le dice al sistema operativo que comience una nueva línea. Sin embargo, aparentemente no contiene caracteres de nueva línea.
Ejecutando el último JDK en Windows XP SP3.
¿Algunas ideas?
El problema
NO debe asumir que un archivo de texto de entrada arbitrario utiliza el separador de newline "correcto" específico de la plataforma. Esta parece ser la fuente de tu problema; Tiene poco que ver con expresiones regulares.
Para ilustrar, en la plataforma Windows, System.getProperty("line.separator")
es "/r/n"
(CR + LF). Sin embargo, cuando ejecuta su código Java en esta plataforma, es posible que tenga que tratar con un archivo de entrada cuyo separador de línea sea simplemente "/n"
(LF). Quizás este archivo se creó originalmente en la plataforma Unix y luego se transfirió en modo binario (en lugar de texto) a Windows. Puede haber muchos escenarios en los que puede encontrarse con este tipo de situaciones, donde debe analizar un archivo de texto como entrada que no utiliza el separador de nueva línea de la plataforma actual.
(Casualmente, cuando un archivo de texto de Windows se transfiere a Unix en modo binario, muchos editores mostrarían ^M
que confundió a algunas personas que no entendían lo que estaba pasando).
Cuando está produciendo un archivo de texto como salida, probablemente debería preferir el separador de nueva línea específico de la plataforma, pero cuando está consumiendo un archivo de texto como entrada, probablemente no sea seguro suponer que utiliza correctamente el separador de nueva línea específico de la plataforma.
La solución
Una forma de resolver el problema es usar, por ejemplo, java.util.Scanner
. Tiene un método nextLine()
que puede devolver la siguiente línea (si existe), que maneja correctamente cualquier inconsistencia entre el separador de nueva línea de la plataforma y el archivo de texto de entrada.
También puede combinar 2 Scanner
, uno para escanear el archivo línea por línea y otro para escanear los tokens de cada línea. Aquí hay un ejemplo de uso simple que divide cada línea en una List<String>
. Por lo tanto, todo el archivo se convierte en una List<List<String>>
.
Este es probablemente un enfoque mejor que leer el archivo completo en una String
enorme y luego split
en líneas (que luego se split
en partes).
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]]
Ver también
- Effective Java 2nd Edition, Item 25: Prefiere listas a arreglos
Preguntas relacionadas
- Validación de entrada usando
java.util.Scanner
- tiene muchos ejemplos de uso - Escáner vs. StringTokenizer vs. String.Split
Creo que su problema es que String.split()
trata su argumento como una expresión regular, y las expresiones regulares tratan las nuevas líneas especialmente. Es posible que deba crear explícitamente un objeto de expresión regular para pasar a split()
(hay otra sobrecarga de él) y configurar esa expresión regular para permitir nuevas líneas pasando MULTILINE
en el Pattern.compile()
flags de Pattern.compile()
. Docs
En Windows, line.separator es una combinación CR / LF (consulte here ).
El String.split()
Java String.split()
toma una expresión regular . Así que creo que hay algo de confusión aquí.
Intente BufferedReader.readLine()
lugar de toda esta complicación. Reconocerá todos los terminadores de línea posibles.
Los otros respondedores tienen razón en que split () toma una expresión regular como argumento, por lo que tendrá que arreglarlo primero. El otro problema es que está asumiendo que los caracteres de salto de línea son los mismos que los predeterminados del sistema. Dependiendo de dónde provienen los datos y de dónde se está ejecutando el programa, esta suposición puede no ser correcta.
Prueba esto:
rows = tabDelimitedTable.split("[//r//n]+");
Esto debería funcionar independientemente de los delimitadores de línea en la entrada e ignorará las líneas en blanco.
Tratar
rows = tabDelimitedTable.split("[" + newLine + "]");
Esto debería resolver el problema de expresiones regulares .
Tampoco es tan importante sino el tipo de retorno.
System.getProperty("line.separator")
es String, por lo que no es necesario llamar a toString ().