Dividir Java String por nova linha

390

Estou tentando dividir o texto em um JTextAreausando uma regex para dividir a String por \nNo entanto, isso não funciona e também tentei por \r\n|\r|ne muitas outras combinações de regexes. 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
fonte
7
qual é o erro que você recebe? Não diga "não funciona", isso não significa nada. Diga-nos o erro / resultado obtido. Esse é o primeiro passo na depuração de código - descubra qual é o resultado errado e como o seu programa chegou a isso.
181 Chii
O que você realmente quer fazer? - quebra de linhas à medida que são inseridas na JTextArea? - localizando onde o JTextArea está fazendo a quebra de linha? - ???
user85421

Respostas:

732

Isso deve cobrir você:

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

Existem apenas duas novas linhas (UNIX e Windows) com as quais você precisa se preocupar.

cleto
fonte
43
Um documento JTextArea DEVE usar apenas '\ n'; suas vistas ignoram completamente '\ r'. Mas se você estiver procurando por mais de um tipo de separador, procure os três: "\ r? \ N | \ r".
Alan Moore
10
Mac 9 usa \ r. OSX 10 usa \ n
Raekye
$ {fn: length (fn: split (data, '\\ r? \\ n'))}} não está funcionando no jstl
4
@antak sim, splitpor padrão remove as seqüências de caracteres vazias à direita se elas resultarem em divisão. Para desativar esse mecanismo, você precisa usar a versão sobrecarregada do split(regex, limit)com limite negativo como text.split("\\r?\\n", -1). Mais informações: Java Separa strings removido valores vazios
Pshemo
11
O comentário de @stivlo é desinformação e é lamentável que tenha tantos votos positivos. Como @ Raekye apontou, o OS X (agora conhecido como macOS) usou \ n como separador de linhas desde que foi lançado em 2001. O Mac OS 9 foi lançado em 1999 e nunca vi um computador com Mac OS 9 ou inferior usado em produção. Não existe um único sistema operacional moderno que use \ r como separador de linhas. NUNCA escreva códigos que esperem que seja o separador de linhas no Mac, a menos que a) você goste de computação retroativa, b) tenha uma máquina OS 9 ativada ec) possa determinar com segurança que a máquina é realmente OS 9.
James McLaughlin
133

String#split​(String regex)O método está usando regex (expressões regulares). Como o Java 8 regex suporta o \Rque representa (da documentação da classe Pattern ):

Matcher de quebra de linha
\ R Qualquer sequência de quebra de linha Unicode é equivalente a \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]

Para que possamos usá-lo para combinar:

Como você vê, \r\né colocado no início do regex, o que garante que o regex tentará corresponder esse par primeiro e, somente se essa correspondência falhar, ele tentará corresponder aos separadores de linha de caracteres únicos .


Portanto, se você deseja dividir no separador de linha, use split("\\R").

Se você não deseja remover da matriz resultante, as seqüências de caracteres vazias são"" usadas split(regex, limit)com limitparâmetros negativos como split("\\R", -1).

Se você deseja tratar uma ou mais linhas vazias contínuas como uso de delimitador único split("\\R+").

Pshemo
fonte
4
Sim, é a melhor resposta. Infelizmente, a pergunta foi feita seis anos antes da resposta.
Dawood ibn Kareem
Acabei me separando \\R+, para evitar qualquer caractere de final de linha que não fosse coberto \\Rsozinho.
SeverityOne
128

Se você não quiser linhas vazias:

String.split("[\\r\\n]+")
quiabo
fonte
4
barras invertidas duplas são desnecessárias, consulte a seção "Barras invertidas, escapes e citações" docs.oracle.com/javase/1.4.2/docs/api/java/util/regex/…
angryITguy 5/11
11
Isso funcionou no Mac OSX quando a resposta acima não.
John
Isso também funcionou para mim. Excelente solução. Funcionou nos 2 casos seguintes: 1) acordei às 3 horas. \ R \ n \ r \ nEu espero 2) isso é a vida real \ r \ nso I
logixplayer
2
@tresf Você não pode usar quantificadores entre colchetes.
CX gamer
49
String.split(System.getProperty("line.separator"));

Isso deve ser independente do sistema

Shervin Asgari
fonte
41
É uma ideia interessante, mas você deve se certificar de que o texto realmente use o separador de linhas do sistema. Eu tenho muitos arquivos de texto no unix (por exemplo, XML) que usa separadores "Windows" e muitos no Windows que usam separadores unix.
Maarten Bodewes
Funciona mesmo no android
Rux
6
Os arquivos criados em um sistema operacional Windows e transferidos para um sistema operacional Unix ainda conterão \ r \ n separadores. Eu acho que é melhor jogar pelo seguro e levar em consideração os dois separadores.
Bdbb
17
Esta é uma abordagem muito problemática! O arquivo pode não se originar do sistema executando o código. Eu desencorajo fortemente esses tipos de projetos "independentes do sistema" que realmente dependem de um sistema específico, o sistema de tempo de execução.
Martin
4
@ Shervin Nunca é a melhor maneira de fazê-lo. Na verdade, é uma prática muito ruim. Considere outro programador chamado System.setProperty ("line.separator", "você não tem sentido"); Seu código está quebrado. Pode até ser chamado de maneira semelhante por uma dependência sobre a qual você não tem conhecimento.
Martin
14

Um novo método linesfoi introduzido na Stringclasse em, que retorna Stream<String>

Retorna um fluxo de substrings extraídos dessa string particionada por terminadores de linha.

Terminadores de linha reconhecidos são avanço de linha "\ n" (U + 000A), retorno de carro "\ r" (U + 000D) e retorno de carro seguido imediatamente por um avanço de linha "\ r \ n" (U + 000D U + 000A )

Aqui estão alguns exemplos:

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

String # lines ()

Anton Balaniuc
fonte
12

Você não precisa dobrar caracteres de escape em grupos de caracteres.

Para todas as linhas não vazias, use:

String.split("[\r\n]+")
Martin
fonte
Sim você faz. Se eles precisam escapar duas vezes em qualquer lugar, precisam disso em qualquer lugar. O espaço em branco escapa como \re \npode ter uma ou duas barras invertidas; eles funcionam de qualquer maneira.
Alan Moore
2
A barra invertida dupla '\\'no código se torna um '\'caractere e depois é passada para o mecanismo RegEx, portanto, o "[\\r\\n]"código fica [\r\n]na memória e o RegEx processará isso. Não sei exatamente como o Java lida com o RegEx, mas é uma boa prática passar um padrão de seqüência de caracteres ASCII "puro" para o mecanismo RegEx e deixá-lo processar em vez de passar caracteres binários. "[\r\n]"fica (hex) 0D0Ana memória e um mecanismo RegEx pode aceitá-lo enquanto outro engasga. Assim a linha inferior é que, mesmo se o sabor de RegEx de Java não precisa delas, mantenha barras duplas para compatibilidade
nurchi
10

JDK11Na Stringclasse tem um lines()método:

Retornando um fluxo de linhas extraídas dessa sequência, separadas por terminadores de linha.

Além disso, a documentação continua dizendo:

Um terminador de linha é um dos seguintes: um caractere de avanço de linha "\ n" (U + 000A), um caractere de retorno de carro "\ r" (U + 000D) ou um retorno de carro seguido imediatamente por um avanço de linha "\ r \ n "(U + 000D U + 000A). Uma linha é uma sequência de zero ou mais caracteres seguida por um terminador de linha, ou é uma sequência de um ou mais caracteres seguida pelo final da sequência. Uma linha não inclui o terminador de linha.

Com isso, pode-se simplesmente fazer:

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

então se você deseja uma matriz:

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

Dado que esse método retorna um Stream, ele oferece muitas opções, pois permite escrever expressões concisas e declarativas de operações possivelmente paralelas.

Ousmane D.
fonte
7

Talvez isso funcione:

Remova as barras invertidas duplas do parâmetro do método de divisão:

split = docStr.split("\n");
Michael
fonte
8
Na verdade não. Quando você escreve um regex na forma de um literal Java String, pode usar "\ n" para transmitir ao compilador regex um símbolo de avanço de linha ou "\\ n" para passar a sequência de escape para um avanço de linha. O mesmo vale para todos os outros espaços em branco, exceto \ v, que não é suportado em literais Java.
277 Alan Moore Alan
3
@Yuval. Desculpe, mas você não precisa disso " Barras
angryITguy
7

Todas as respostas fornecidas aqui, na verdade, não respeitam a definição de novas linhas do Javas, como em, por exemplo, BufferedReader # readline. Java está aceitando \n, \re \r\ncomo nova linha. Algumas das respostas correspondem a várias linhas vazias ou arquivos malformados. Por exemplo. <sometext>\n\r\n<someothertext>o uso [\r\n]+resultaria em duas linhas.

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

Por outro lado, a resposta acima tem as seguintes propriedades:

  • está em conformidade com a definição de Javas de uma nova linha, como por exemplo, o BufferedReader está usando
  • não corresponde a várias novas linhas
  • ele não remove as linhas vazias à direita
Até Schäfer
fonte
6

Se, por algum motivo, você não desejar usar String.split(por exemplo, devido a expressões regulares ) e desejar usar a programação funcional no Java 8 ou mais recente:

List<String> lines = new BufferedReader(new StringReader(string))
        .lines()
        .collect(Collectors.toList());
Danilo Piazzalunga
fonte
Eu sei que isso pode ser uma solução exagerada.
Danilo Piazzalunga
3
Ou String[] lines = new BufferedReader(...).lines().toArray(String[]::new);para uma matriz em vez de uma lista. O legal dessa solução é que você BufferedReaderconhece todos os tipos de terminadores semelhantes, para que ele possa manipular texto em todos os tipos de formatos. (A maioria das soluções baseadas em regex postado aqui ficam aquém neste aspecto.)
Ted Hopp
2
Esta solução está obsoleta desde o Java 11 e a introdução do método String.lines ().
leventov
4

Para evitar que linhas vazias sejam esmagadas, use:

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

O código acima não faz nada visível - apenas calcula e depois despeja o cálculo. É o código que você usou ou apenas um exemplo para esta pergunta?

tente fazer textAreaDoc.insertString (int, String, AttributeSet) no final?

Chii
fonte
insertUpdate () é um método DocumentListener. Supondo que o OP esteja usando corretamente, tentar modificar o documento de dentro do método listener gerará uma exceção. Mas você está certo: o código nessa pergunta não faz nada.
Alan Moore
2

Como alternativa às respostas anteriores, a SplitterAPI da goiaba pode ser usada se outras operações forem aplicadas às linhas resultantes, como aparar linhas ou filtrar linhas vazias:

import com.google.common.base.Splitter;

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

Observe que o resultado é um Iterablee não um array.

Thomas Naskali
fonte
1

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

Husayt
fonte
1

Após tentativas fracassadas com base em todas as soluções fornecidas. Eu substituo \npor alguma palavra especial e depois divido. Para mim, segui o truque:

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

Não pude replicar o exemplo dado na pergunta. Mas acho que essa lógica pode ser aplicada.

kravi
fonte
1

As respostas acima não me ajudaram no Android, graças à resposta Pshemo que funcionou para mim no Android. Vou deixar aqui algumas das respostas de Pshemo :

split("\\\\n")
clasher
fonte
0
  • tente esta esperança foi útil para você

 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
fonte
0

Existem três convenções diferentes (pode-se dizer que esses são padrões de fato ) para definir e exibir uma quebra de linha:

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

Em alguns editores de texto, é possível trocar um pelo outro:

Notepad ++

A coisa mais simples é normalizar line feede depois dividir.

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

Há um garoto novo na cidade, então você não precisa lidar com todas as complexidades acima. A partir do JDK 11 , basta escrever como uma única linha de código, ele dividirá as linhas e retornará o 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
}}

Algumas referências. https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#lines () https://www.azul.com/90-new -features-and-apis-in-jdk-11 /

Espero que isso seja útil para alguém. Feliz codificação.

Menino vermelho
fonte
-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
fonte
Isso empalidece em comparação com as outras respostas, que são mais explicativas e menos pesadas em código. Você poderia explicar o que está realizando com este código e por que ele daria uma resposta adequada?
Makoto
2
Isso não tem nada a ver com a divisão de um arquivo em linhas. Considere remover sua resposta.
Martin