Split Java String por New Line

390

Estoy tratando de dividir el texto JTextAreausando una expresión regular para dividir la cadena por \nSin embargo, esto no funciona y también probé con \r\n|\r|nmuchas otras combinaciones de expresiones regulares. Código:

public void insertUpdate(DocumentEvent e) {
    String split[], docStr = null;
    Document textAreaDoc = (Document)e.getDocument();

    try {
        docStr = textAreaDoc.getText(textAreaDoc.getStartPosition().getOffset(), textAreaDoc.getEndPosition().getOffset());
    } catch (BadLocationException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }

    split = docStr.split("\\n");
}
Dr. Manhattan
fuente
77
¿Cuál es el error que obtienes? No digas "no funciona", eso no significa nada. Dinos el error / resultado que obtienes. Ese es el primer paso en la depuración de código: descubra cuál es el resultado incorrecto y cómo su programa llegó a eso.
Chii
¿Qué es lo que realmente quieres hacer? - ¿Rompe líneas a medida que se ingresan en JTextArea? - ¿Dónde se encuentra JTextArea haciendo ajustes de línea? - ???
user85421

Respuestas:

732

Esto debería cubrirlo:

String lines[] = string.split("\\r?\\n");

Solo hay dos líneas nuevas (UNIX y Windows) de las que debe preocuparse.

cletus
fuente
43
Un documento JTextArea DEBE usar solo '\ n'; sus Vistas ignoran por completo '\ r'. Pero si va a buscar más de un tipo de separador, también podría buscar los tres: "\ r? \ N | \ r".
Alan Moore
10
Mac 9 usa \ r. OSX 10 usa \ n
Raekye
$ {fn: length (fn: split (data, '\\ r? \\ n'))} no funciona en jstl
44
@antak sí, splitpor defecto elimina las cadenas vacías finales si son resultado de una división. Para desactivar este mecanismo, debe utilizar una versión sobrecargada split(regex, limit)con límite negativo como text.split("\\r?\\n", -1). Más información: Java String split eliminó valores vacíos
Pshemo
1
El comentario de @stivlo es información errónea, y es lamentable que tenga tantos votos positivos. Como señaló @ Raekye, OS X (ahora conocido como macOS) ha usado \ n como su separador de línea desde su lanzamiento en 2001. Mac OS 9 fue lanzado en 1999, y nunca he visto una máquina Mac OS 9 o inferior utilizada en producción. No hay un solo sistema operativo moderno que use \ r como separador de línea. NUNCA escriba código que espere que \ r sea el separador de línea en Mac, a menos que a) esté interesado en la informática retro, b) tenga una máquina con OS 9 puesta en marcha yc) pueda determinar de manera confiable que la máquina es realmente OS 9.
James McLaughlin
133

String#split​(String regex)El método está utilizando expresiones regulares (expresiones regulares). Como Java 8 regex es compatible con lo \Rque representa (de la documentación de la clase Pattern ):

Linebreak matcher
\ R Cualquier secuencia de salto de línea Unicode, es equivalente a \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Entonces podemos usarlo para que coincida con:

Como puede ver, \r\nse coloca al comienzo de la expresión regular, lo que garantiza que la expresión regular intentará hacer coincidir este par primero, y solo si esa coincidencia falla, intentará hacer coincidir los separadores de línea de un solo carácter .


Entonces, si desea dividir el uso del separador de línea split("\\R").

Si no desea eliminar de la matriz resultante las cadenas vacías finales,"" use parámetros split(regex, limit)negativos limitcomo split("\\R", -1).

Si desea tratar una o más líneas continuas vacías como uso delimitador único split("\\R+").

Pshemo
fuente
44
Sí, es la mejor respuesta. Lamentablemente, la pregunta se hizo con seis años de anticipación para esta respuesta.
Dawood ibn Kareem el
Terminé dividiéndome \\R+para evitar cualquier personaje de final de línea que no estuviera cubierto \\Rsolo.
SeverityOne
128

Si no quieres líneas vacías:

String.split("[\\r\\n]+")
Gumbo
fuente
44
las barras invertidas dobles son innecesarias, consulte la sección " Barras
invertidas
1
Esto funcionó en Mac OSX cuando la respuesta anterior no.
John
Esto también funcionó para mí. Excelente solucion. Funcionó para los siguientes 2 casos: 1) me desperté a las 3 en punto. \ R \ n \ r \ nEspero 2) esta es la vida real \ r \ nso I
logixplayer
2
@tresf No puede usar cuantificadores entre corchetes.
CX gamer
49
String.split(System.getProperty("line.separator"));

Esto debería ser independiente del sistema

Shervin Asgari
fuente
42
Es una idea interesante, pero debe tener cuidado de que el texto realmente use el separador de línea del sistema. Tengo muchos archivos de texto en Unix (por ejemplo, XML) que usan separadores de "Windows" y muchos en Windows que usan separadores de Unix.
Maarten Bodewes
Funciona incluso en Android
ruX
77
Los archivos creados en un sistema operativo Windows y transferidos a un sistema operativo Unix seguirán conteniendo \ r \ n separadores. Creo que es mejor ir a lo seguro y tener en cuenta a los dos separadores.
bvdb
17
Este es un enfoque muy problemático! Es posible que el archivo no se origine en el sistema que ejecuta el código. Desaconsejo encarecidamente este tipo de diseños "independientes del sistema" que en realidad dependen de un sistema específico, el sistema de tiempo de ejecución.
Martin
44
@Shervin Nunca es la mejor manera de hacerlo. De hecho, es una muy mala práctica. Considere algún otro programador que llame a System.setProperty ("line.separator", "no tiene sentido"); Tu código está roto. Incluso podría ser llamado de manera similar por una dependencia de la que no tiene conocimiento.
Martin
14

Se linesha introducido un nuevo método para la Stringclase en, que devuelve Stream<String>

Devuelve una secuencia de subcadenas extraídas de esta cadena dividida por terminadores de línea.

Los terminadores de línea reconocidos son el avance de línea "\ n" (U + 000A), el retorno de carro "\ r" (U + 000D) y un retorno de carro seguido inmediatamente por un avance de línea "\ r \ n" (U + 000D U + 000A )

Aquí están algunos ejemplos:

jshell> "lorem \n ipusm \n sit".lines().forEach(System.out::println)
lorem
 ipusm
 sit

jshell> "lorem \n ipusm \r  sit".lines().forEach(System.out::println)
lorem
 ipusm
  sit

jshell> "lorem \n ipusm \r\n  sit".lines().forEach(System.out::println)
lorem
 ipusm
  sit

Cadena # líneas ()

Anton Balaniuc
fuente
12

No tiene que duplicar los caracteres de escape en los grupos de personajes.

Para todas las líneas no vacías use:

String.split("[\r\n]+")
Martín
fuente
Si tu puedes. Si necesitan doble escape en cualquier lugar, lo necesitan en todas partes. El espacio en blanco se escapa como \ry \npuede tener una o dos barras invertidas; funcionan de cualquier manera.
Alan Moore
2
La doble barra diagonal inversa '\\'en el código se convierte en un '\'carácter y luego se pasa al motor RegEx, por lo que el "[\\r\\n]"código se convierte [\r\n]en memoria y RegEx procesará eso. No sé exactamente cómo Java maneja RegEx, pero es una buena práctica pasar un patrón de cadena ASCII "puro" al motor RegEx y dejar que procese en lugar de pasar caracteres binarios. "[\r\n]"se convierte en (hexadecimal) 0D0Aen la memoria y un motor RegEx podría aceptarlo mientras que otro se ahogará. La conclusión es que, incluso si el sabor de RegEx de Java no los necesita, mantenga dos barras diagonales para compatibilidad
nurchi el
10

En JDK11la Stringclase tiene un lines()método:

Devuelve una secuencia de líneas extraídas de esta cadena, separadas por terminadores de línea.

Además, la documentación continúa diciendo:

Un terminador de línea es uno de los siguientes: un carácter de avance de línea "\ n" (U + 000A), un carácter de retorno de carro "\ r" (U + 000D) o un retorno de carro seguido inmediatamente por un avance de línea "\ r \ n "(U + 000D U + 000A). Una línea es una secuencia de cero o más caracteres seguidos de un terminador de línea, o es una secuencia de uno o más caracteres seguidos del final de la cadena. Una línea no incluye el terminador de línea.

Con esto uno simplemente puede hacer:

Stream<String> stream = str.lines();

entonces si quieres una matriz:

String[] array = str.lines().toArray(String[]::new);

Dado que este método devuelve un Stream, ofrece muchas opciones para usted, ya que le permite a uno escribir expresiones concisas y declarativas de operaciones posiblemente paralelas.

Ousmane D.
fuente
7

Quizás esto funcionaría:

Elimine las barras invertidas dobles del parámetro del método de división:

split = docStr.split("\n");
Miguel
fuente
8
Realmente no. Cuando escribe una expresión regular en forma de un literal de cadena Java, puede usar "\ n" para pasar al compilador de expresiones regulares un símbolo de salto de línea, o "\\ n" para pasarle la secuencia de escape para un salto de línea. Lo mismo ocurre con todos los demás escapes de espacios en blanco, excepto \ v, que no es compatible con los literales de Java.
Alan Moore
3
@Yuval. Lo sentimos, es incorrecto, no lo necesita en absoluto "Barras, escapes y citas
angryITguy
7

Todas las respuestas dadas aquí en realidad no respetan la definición de Javas de nuevas líneas como se da en, por ejemplo, BufferedReader # readline. Java está aceptando \n, \ry \r\ncomo nueva línea. Algunas de las respuestas coinciden con varias líneas vacías o archivos con formato incorrecto. P.ej. <sometext>\n\r\n<someothertext>cuando se usa [\r\n]+daría como resultado dos líneas.

String lines[] = string.split("(\r\n|\r|\n)", -1);

Por el contrario, la respuesta anterior tiene las siguientes propiedades:

  • cumple con la definición de Javas de una nueva línea como, por ejemplo, BufferedReader lo está utilizando
  • no coincide con varias líneas nuevas
  • no elimina las líneas vacías finales
Hasta Schäfer
fuente
6

Si, por alguna razón, no desea utilizar String.split(por ejemplo, debido a expresiones regulares ) y desea utilizar la programación funcional en Java 8 o posterior:

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());
Danilo Piazzalunga
fuente
Sé que esto puede ser una solución exagerada.
Danilo Piazzalunga
3
O String[] lines = new BufferedReader(...).lines().toArray(String[]::new);para una matriz en lugar de una lista. Lo bueno de esta solución es que BufferedReaderconoce todo tipo de terminadores similares, por lo que puede manejar texto en todo tipo de formatos. (La mayoría de las soluciones basadas en expresiones regulares publicadas aquí se quedan cortas en este sentido.)
Ted Hopp
2
Esta solución es obsoleta desde Java 11 y la introducción del método String.lines ().
leventov
4

Para evitar que las líneas vacías se aplasten, use:

String lines[] = String.split("\\r?\\n", -1);
sevenforce
fuente
3

El código anterior en realidad no hace nada visible: simplemente se calcula y luego volca el cálculo. ¿Es el código que usó o solo un ejemplo para esta pregunta?

intente hacer textAreaDoc.insertString (int, String, AttributeSet) al final?

Chii
fuente
insertUpdate () es un método DocumentListener. Suponiendo que el OP lo esté utilizando correctamente, intentar modificar el documento desde dentro del método de escucha generará una excepción. Pero tienes razón: el código en esa pregunta en realidad no hace nada.
Alan Moore
2

Como alternativa a las respuestas anteriores, la SplitterAPI de guayaba se puede usar si se van a aplicar otras operaciones a las líneas resultantes, como recortar líneas o filtrar líneas vacías:

import com.google.common.base.Splitter;

Iterable<String> split = Splitter.onPattern("\r?\n").trimResults().omitEmptyStrings().split(docStr);

Tenga en cuenta que el resultado es una Iterabley no una matriz.

Thomas Naskali
fuente
1

String lines[] =String.split( System.lineSeparator())

husayt
fuente
1

Después de intentos fallidos sobre la base de todas las soluciones dadas. Reemplazo \ncon una palabra especial y luego me separo. Para mí siguiente hizo el truco:

article = "Alice phoned\n bob.";
article = article.replace("\\n", " NEWLINE ");
String sen [] = article.split(" NEWLINE ");

No pude replicar el ejemplo dado en la pregunta. Pero, supongo que esta lógica se puede aplicar.

kravi
fuente
1

Las respuestas anteriores no me ayudaron en Android, gracias a la respuesta de Pshemo que funcionó para mí en Android. Dejaré algunas de las respuestas de Pshemo aquí:

split("\\\\n")
enfrentamiento
fuente
0
  • prueba esta esperanza, fue útil para ti

 String split[], docStr = null;
Document textAreaDoc = (Document)e.getDocument();

try {
    docStr = textAreaDoc.getText(textAreaDoc.getStartPosition().getOffset(), textAreaDoc.getEndPosition().getOffset());
} catch (BadLocationException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

split = docStr.split("\n");
Vishal Yadav
fuente
0

Hay tres convenciones diferentes (se podría decir que son estándares de facto ) para establecer y mostrar un salto de línea:

  • carriage return + line feed
  • line feed
  • carriage return

En algunos editores de texto, es posible intercambiar uno por el otro:

Notepad ++

Lo más simple es normalizar line feedy luego dividir.

final String[] lines = contents.replace("\r\n", "\n")
                               .replace("\r", "\n")
                               .split("\n", -1);
Paul Vargas
fuente
0

Hay un chico nuevo en la ciudad, por lo que no debes lidiar con todas las complejidades anteriores. A partir de JDK 11 en adelante , solo necesita escribir como una sola línea de código, dividirá las líneas y le devolverá Stream of String.

public class MyClass {
public static void main(String args[]) {
   Stream<String> lines="foo \n bar \n baz".lines();
   //Do whatever you want to do with lines
}}

Algunas referencias https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#lines () https://www.azul.com/90-new -características-y-apis-en-jdk-11 /

Espero que esto sea útil para alguien. Feliz codificación

Chico rojo
fuente
-1
package in.javadomain;

public class JavaSplit {

    public static void main(String[] args) {
        String input = "chennai\nvellore\ncoimbatore\nbangalore\narcot";
        System.out.println("Before split:\n");
        System.out.println(input);

        String[] inputSplitNewLine = input.split("\\n");
        System.out.println("\n After split:\n");
        for(int i=0; i<inputSplitNewLine.length; i++){
            System.out.println(inputSplitNewLine[i]);
        }
    }

}
Naveen
fuente
Esto palidece en comparación con las otras respuestas, que son más explicativas y tienen menos código. ¿Podría explicar qué es lo que está logrando con este código y por qué sería una respuesta adecuada?
Makoto
2
Esto no tiene nada que ver con dividir un archivo en líneas. Considera eliminar tu respuesta.
Martin