Como crio uma string Java a partir do conteúdo de um arquivo?


1513

Estou usando o idioma abaixo há algum tempo. E parece ser o mais difundido, pelo menos nos sites que visitei.

Existe uma maneira melhor / diferente de ler um arquivo em uma string em Java?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}

7
Alguém pode me explicar de uma maneira muito simples o que há com a NIO? Cada vez que eu leio sobre isso, eu me perco na enésima menção de channel :(
OscarRyz

7
lembre-se de que não é garantido que o separador de linhas no arquivo não seja necessário da mesma forma que o separador de linhas do sistema.
286 Henrik Paul

138
Você poderia finalmente inserir uma tentativa adequada que feche o leitor? Alguém pode realmente usar este exemplo e introduzir um bug em seu código.
Hans-Peter Störr

6
O código acima tem um erro de adicionar caracteres extras de nova linha na última linha. Deve ser algo como seguir if (line = reader.readLine ())! = Null) {stringBuilder.append (line); } while (line = reader.readLine ())! = null) {stringBuilder.append (ls); stringBuilder.append (linha); }
Profundo

27
O Java 7 apresenta byte[] Files.readAllBytes(file);Para aqueles que sugerem a solução de scanner de uma linha: Você não precisa fechá-la?
Val

Respostas:


1535

Leia todo o texto de um arquivo

O Java 11 adicionou o método readString () para ler arquivos pequenos como um String, preservando os terminadores de linha:

String content = Files.readString(path, StandardCharsets.US_ASCII);

Para versões entre Java 7 e 11, aqui está um idioma compacto e robusto, agrupado em um método utilitário:

static String readFile(String path, Charset encoding) 
  throws IOException 
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

Ler linhas de texto de um arquivo

O Java 7 adicionou um método de conveniência para ler um arquivo como linhas de texto, representadas como a List<String>. Essa abordagem é "com perda" porque os separadores de linha são removidos do final de cada linha.

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

O Java 8 adicionou o Files.lines()método para produzir a Stream<String>. Novamente, esse método está com perdas porque os separadores de linha são removidos. Se um IOExceptionfor encontrado durante a leitura do arquivo, ele será agrupado em um UncheckedIOException, já Streamque não aceita lambdas que geram exceções verificadas.

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

Isso Streamprecisa de uma close()ligação; isso está mal documentado na API e suspeito que muitas pessoas nem percebem que Streamtem umclose() método. Certifique-se de usar um bloco ARM, como mostrado.

Se você estiver trabalhando com uma fonte que não seja um arquivo, poderá usar o lines()método emBufferedReader vez disso.

Utilização de memória

O primeiro método, que preserva as quebras de linha, pode exigir temporariamente memória várias vezes o tamanho do arquivo, porque por um curto período de tempo o conteúdo do arquivo bruto (uma matriz de bytes) e os caracteres decodificados (cada um com 16 bits, mesmo que codificado) 8 bits no arquivo) residem na memória de uma só vez. É mais seguro aplicar a arquivos que você sabe serem pequenos em relação à memória disponível.

O segundo método, linhas de leitura, geralmente é mais eficiente em memória, porque o buffer de bytes de entrada para decodificação não precisa conter o arquivo inteiro. No entanto, ainda não é adequado para arquivos muito grandes em relação à memória disponível.

Para ler arquivos grandes, você precisa de um design diferente para o seu programa, que leia um pedaço de texto de um fluxo, o processe e depois passe para o próximo, reutilizando o mesmo bloco de memória de tamanho fixo. Aqui, "grande" depende das especificações do computador. Atualmente, esse limite pode ser de muitos gigabytes de RAM. O terceiro método, usando a, Stream<String>é uma maneira de fazer isso, se os "registros" de entrada forem linhas individuais. (Usar o readLine()método de BufferedReaderé o equivalente processual a essa abordagem.)

Codificação de caracteres

Uma coisa que está faltando na amostra na postagem original é a codificação de caracteres. Existem alguns casos especiais em que o padrão da plataforma é o que você deseja, mas eles são raros e você deve justificar sua escolha.

A StandardCharsetsclasse define algumas constantes para as codificações necessárias para todos os tempos de execução do Java:

String content = readFile("test.txt", StandardCharsets.UTF_8);

O padrão da plataforma está disponível naCharset própria classe :

String content = readFile("test.txt", Charset.defaultCharset());

Nota: Esta resposta substitui amplamente minha versão do Java 6. O utilitário do Java 7 simplifica com segurança o código, e a resposta antiga, que usava um buffer de bytes mapeados, impedia que o arquivo lido fosse excluído até que o buffer mapeado fosse coletado de lixo. Você pode visualizar a versão antiga através do link "editado" nesta resposta.


3
Tecnicamente falando, é O (n) no tempo e no espaço. Qualitativamente, devido ao requisito de imutabilidade do Strings, é bastante difícil de memorizar; temporariamente, existem duas cópias dos dados char na memória, além da sala para os bytes codificados. Supondo alguma codificação de byte único, será necessário (temporariamente) 5 bytes de memória para cada caractere no arquivo. Como a pergunta pede especificamente uma String, é isso que eu mostro, mas se você pode trabalhar com o CharBuffer retornado por "decode", o requisito de memória é muito menor. Em termos de tempo, acho que você não encontrará nada mais rápido nas principais bibliotecas Java.
21416

5
Possível erro de digitação? O NIO possui uma classe Charset (não CharSet) chamada java.nio.charset.Charset. É isso que CharSet deveria ter sido?
23611 Jonathan Wright

31
Nota: depois de exercitar um pouco esse código, descobri que você não pode excluir o arquivo de maneira confiável logo após lê-lo com este método, o que pode ser um problema não, em alguns casos, mas não o meu. Pode estar relacionado a este problema: bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? Finalmente fui com a proposta de Jon Skeet, que não sofre com esse bug. Enfim, eu só queria dar a informação, para outras pessoas, apenas no caso de ...
Sébastien Nussbaumer

5
@ Sébastien Nussbaumer: Eu também esbarrei neste problema. Incrível que o bug tenha sido marcado como "Não será corrigido". Isso significa essencialmente que FileChannel#map, em geral, é inutilizável.
Joonas Pulakka

4
@ Sébastien Nussbaumer: O bug foi excluído do Banco de Dados Oracle / Sun Bug: "Este bug não está disponível." Google em cache o local em webcache.googleusercontent.com/search?q=cache:bugs.sun.com/...
bobndrew

351

Se você deseja usar uma biblioteca externa, consulte o Apache Commons IO (200KB JAR). Ele contém um org.apache.commons.io.FileUtils.readFileToString()método que permite ler um inteiro Fileem um Stringcom uma linha de código.

Exemplo:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}

Não encontro esse método no URL que você fornece.
OscarRyz 28/11/08

2
Está na classe org.apache.commons.io.FileUtils
Cyrille Ka

2
Também estou usando o FileUtils, mas estou me perguntando o que é melhor entre usar o FileUtils ou a resposta nio aceita?
Guillaume

4
@ Guillaume: A maior questão é se você se sente à vontade em depender de uma biblioteca de terceiros. Se você possui Commons IO ou Guava em seu projeto, use-o (apenas para simplificar o código; caso contrário, provavelmente não haverá uma diferença perceptível).
Jonik

183

Uma solução muito enxuta baseada em Scanner:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Ou, se você deseja definir o conjunto de caracteres:

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

Ou, com um bloco try-with-resources , que chamará scanner.close()você:

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

Lembre-se de que o Scannerconstrutor pode lançar um IOException. E não se esqueça de importar java.ioe java.util.

Fonte: Blog de Pat Niemeyer


4
\\ A funciona porque não há "outro começo de arquivo", então você realmente lê o último token ... que também é o primeiro. Nunca tentei com \\ Z. Observe também que você pode ler qualquer coisa que seja legível, como Arquivos, InputStreams, canais ... Às vezes uso esse código para ler na janela de exibição do eclipse, quando não tenho certeza se estou lendo um arquivo ou outro .. .im, o caminho da classe me confunde.
Pablo Grisafi

1
Como pôster, posso dizer que realmente não sei se e quando o arquivo está corretamente fechado ... Nunca escrevo este em código de produção, apenas o utilizo para testes ou depuração.
Pablo Grisafi

2
Acho que tem um limite de 1024 caracteres
Whimusical

20
O scanner implementa o Closeable (invoca de perto a fonte) - portanto, embora seja elegante, não deve ser apenas uma linha. O tamanho padrão do buffer é 1024, mas o Scanner aumentará o tamanho conforme necessário (consulte Scanner # makeSpace ())
earcam

8
Este falha em arquivos vazios com a java.util.NoSuchElementException.
SpaceTrucker

117
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

desde o java 7, você pode fazer dessa maneira.


Isso deve ser aceito como resposta - linha única, sem bibliotecas externas.
Cherry

Isso adicionou um caractere de nova linha no final, mesmo que não estivesse presente no arquivo.
Stefan Haberl

79

Se você estiver procurando por uma alternativa que não envolva uma biblioteca de terceiros (por exemplo, Commons I / O ), use a classe Scanner :

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());        

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}

2
Eu acho que esse é o melhor caminho. Confira java.sun.com/docs/books/tutorial/essential/io/scanning.html
Tarski

3
O construtor Scanner que aceita uma String não trata a string como o nome de um arquivo a ser lido, mas como o texto a ser verificado. Eu cometo esse erro o tempo todo. : - /
Alan Moore

@ Alan, boa captura. Eu editei a resposta de Don um pouco para corrigir isso (espero).
Jonik

3
fileContents.append (scanner.nextLine ()). append (lineSeparator);
ban-geoengineering

1
Altere a instrução de inicialização para Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. Caso contrário, você poderá capturar apenas parte do arquivo.
Wei Yang

71

A goiaba tem um método semelhante ao do Commons IOUtils que Willi aus Rohr mencionou:

import com.google.common.base.Charsets;
import com.google.common.io.Files;

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

EDIT by PiggyPiglet
Files#toString está obsoleto e com a remoção do Octobor 2019. Em vez disso, use Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

EDIT por Oscar Reyes

Este é o código subjacente (simplificado) da biblioteca citada:

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

Editar (por Jonik): O texto acima não corresponde ao código fonte das versões recentes do Guava. Para a fonte atual, consulte as classes Arquivos , CharStreams , ByteSource e CharSource no pacote com.google.common.io .


Esse código foi transmitido de long a int, o que pode gerar um comportamento maluco com arquivos grandes. Possui espaços extras e onde você fecha o fluxo de entrada?
Mohamed Taher Alrefaie

@MTA: O fluxo está fechado, observe o uso Closerno CharSource . O código na resposta não é a fonte atual atual da Goiaba.
Jonik

54
import java.nio.file.Files;

.......

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }

6
Ou ainda mais simples:new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

12
ou new String(Files.readAllBytes(Paths.get(filename)));:-)
assafmo 06/04

1
Bem jogado, e para salvar o próximo cara, o Google, Pathsé aparentemente 1,7+ como está FileSystems. (Dang it!)
ruffin

4
É uma pena que esta resposta não tenha mais votos. Eu estava procurando a maneira mais rápida e simples de inserir um arquivo de texto em uma String. É isso e se eu não rolasse para baixo, para baixo e para baixo, teria perdido. O OP deve considerar aceitar esta resposta para movê-la para o topo.
quer

@ Thorn Esta resposta tem um tratamento horrível de erros. Não use esse método no código de produção, ou melhor: nunca.
xehpuk

51

Se você precisar de um processamento de sequência (processamento paralelo), o Java 8 possui a excelente API de Stream.

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

Mais exemplos estão disponíveis nas amostras JDK sample/lambda/BulkDataOperationsque podem ser baixadas da página de download do Oracle Java SE 8

Outro exemplo de um liner

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

O .parallel () acontece depois que você lê as linhas ou antes disso?
Istvan

O trabalho real começa desde que a operação do terminal é coletada (...). O fluxo é preenchido preguiçosamente linha por linha. Não é necessário ler o arquivo inteiro na memória antes do processamento (por exemplo, filtragem e mapeamento).
Andrei N

aparar antes de escolher linhas não vazias?
Thorbjørn Ravn Andersen

50

Esse código normalizará as quebras de linha, que podem ou não ser o que você realmente deseja fazer.

Aqui está uma alternativa que não faz isso e que é (IMO) mais simples de entender do que o código NIO (embora ainda use java.nio.charset.Charset):

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}

1
Desculpe-me por reviver um comentário tão antigo, mas você pretendia passar um objeto String chamado "file", ou deveria ser um objeto File?
Bryan Larson

28

Reuniu todas as maneiras possíveis para ler o arquivo como sequência do disco ou da rede.

  • Goiaba: Google usando classes Resources,Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }

  • APACHE - COMMO IO usando as classes IOUtils, FileUtils

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }

  • Java 8 BufferReader usando API de Stream

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }

  • Classe de scanner com regex \A. que corresponde ao início da entrada.

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }

  • Java 7 ( java.nio.file.Files.readAllBytes)

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }

  • BufferedReaderusando InputStreamReader.

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }

Exemplo com o método principal para acessar os métodos acima.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@Vejo


26

Se é um arquivo de texto, por que não usar o apache commons-io ?

Tem o seguinte método

public static String readFileToString(File file) throws IOException

Se você quiser as linhas como uma lista, use

public static List<String> readLines(File file) throws IOException

25

Desde o JDK 11:

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8

Por que, ah, por que, introduza novos métodos que dependem do conjunto de caracteres padrão em 2018?
mryan

2
@ mryan esse método não depende do conjunto de caracteres padrão do sistema. O padrão é UTF-8, tudo bem.
leventov 24/09/18

@leventov você está certo! Files.readAllLines também! que faz com que os arquivos de API não é muito consistente com métodos mais antigos, mas é para melhor :)
mryan

17

Para ler um arquivo como binário e converter no final

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

16

Com o Java 7, esta é minha opção preferida para ler um arquivo UTF-8:

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Desde o Java 7, o JDK possui a nova java.nio.fileAPI, que fornece muitos atalhos, portanto nem sempre são necessárias bibliotecas de terceiros para operações simples de arquivo.


15

O Java tenta ser extremamente geral e flexível em tudo o que faz. Como resultado, algo que é relativamente simples em uma linguagem de script (seu código seria substituído por " open(file).read()" em python) é muito mais complicado. Parece não haver uma maneira mais curta de fazer isso, exceto usando uma biblioteca externa (como Willi aus Rohr mencionou). Suas opções:

  • Use uma biblioteca externa.
  • Copie esse código em todos os seus projetos.
  • Crie sua própria mini-biblioteca, que contém funções que você usa com freqüência.

Sua melhor aposta é provavelmente a segunda, pois possui menos dependências.


4
Yeap. Faz com que a linguagem de nível "alto" assuma um significado diferente. Java é elevada em comparação com C, mas baixa, em comparação com o Python ou Ruby
OscarRyz

3
Concorda que Java é longa em abstrações de alto nível, mas curto em métodos de conveniência
Donal

3
É verdade que o Java tem um número insano de maneiras de lidar com arquivos e muitas delas parecem complicadas. Mas isso é bastante parecido com o que temos em idiomas de nível superior:byte[] bytes = Files.readAllBytes(someFile.toPath());
Thorn

11

Usando o JDK 8 ou superior:

nenhuma biblioteca externa usada

Você pode criar um novo objeto String a partir do conteúdo do arquivo (Usando classes do java.nio.filepacote):

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

Resposta duplicada de Moritz Petersen que escreveu: String content = new String (Files.readAllBytes (Paths.get (filename)), "UTF-8");
Jean-Christophe Blanchard

8

Há uma variação no mesmo tema que usa um loop for, em vez de um while, para limitar o escopo da variável de linha. Se é "melhor" é uma questão de gosto pessoal.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

3
Isso mudará as novas linhas para a escolha padrão de nova linha. Isso pode ser desejável ou não intencional.
Peter Lawrey

Retrocedeu a edição desta resposta porque o objetivo era restringir o escopo da linevariável. A edição declarou duas vezes, o que seria um erro de compilação.
Dan Dyer

7

Se você não tiver acesso à Filesclasse, poderá usar uma solução nativa.

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}

exemplo charset para invocar?
Thufir

4

Uma solução flexível usando IOUtils do Apache commons-io em combinação com o StringWriter :

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

Funciona com qualquer leitor ou fluxo de entrada (não apenas com arquivos), por exemplo, ao ler de um URL.


3

Esteja ciente de que o uso fileInputStream.available()do número inteiro retornado não precisa representar o tamanho real do arquivo, mas a quantidade de bytes estimada que o sistema deve poder ler do fluxo sem bloquear as E / S. Uma maneira simples e segura pode ser assim

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

Deve-se considerar que essa abordagem não é adequada para codificações de caracteres de vários bytes, como UTF-8.


1
Este código pode fornecer resultados imprevisíveis. De acordo com a documentação do available()método, não há garantia de que o final do arquivo seja atingido no caso de o método retornar 0. Nesse caso, você pode acabar com um arquivo incompleto. O que é pior, o número de bytes realmente lidos pode ser menor que o valor retornado available(), nesse caso, você obtém saída corrompida.
03:

3

Este usa o método RandomAccessFile.readFully, parece estar disponível no JDK 1.0!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}

3

Você pode experimentar a classe Scanner e File, algumas soluções de linhas

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

3

Usuário java.nio.Filespara ler todas as linhas de arquivo.

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

3
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}

Eu acho que isso tem o inconveniente de usar a codificação padrão da plataforma. +1 de qualquer maneira :) #
21810 OscarRyz

7
Parece-me que o bloco finalmente não conhece variáveis ​​definidas no bloco try. O javac 1.6.0_21 lança o erro cannot find symbol.
ceving

Você já tentou seu próprio código? Você definiu o leitor no bloco try / catch, para que não seja acessível no bloco finalmente.
mauron85

2

Ainda não posso comentar outras entradas, então deixarei aqui.

Uma das melhores respostas aqui ( https://stackoverflow.com/a/326448/1521167 ):

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

ainda tem uma falha. Ele sempre coloca o novo caractere de linha no final da string, o que pode causar alguns erros estranhos. Minha sugestão é alterá-lo para:

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

No primeiro caso, você pode adicionar uma nova linha extra no final. no segundo caso, você pode estar omitindo um. Então, ambos estão igualmente errados. Veja este artigo
Patrick Parker

2

Após Ctrl + F'ing após o Scanner, acho que a solução do Scanner também deve ser listada. Da maneira mais fácil de ler, fica assim:

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

Se você usa o Java 7 ou mais recente (e realmente deveria) considere usar o try-with-resources para facilitar a leitura do código. Não há mais coisas pontilhadas espalhando tudo. Mas isso é principalmente uma escolha estilística.

Estou postando isso principalmente por completismo, pois se você precisar fazer muito isso, deve haver coisas em java.nio.file.Files que devem fazer o trabalho melhor.

Minha sugestão seria usar Files # readAllBytes (Path) para pegar todos os bytes e alimentá-lo com a nova String (byte [] Charset) para obter uma String em que você possa confiar. Charsets será mau para você durante a sua vida, então cuidado com isso agora.

Outros deram código e outras coisas, e eu não quero roubar sua glória. ;)


2

Usando esta biblioteca , é uma linha:

String data = IO.from(new File("data.txt")).toString();

1
se as linhas dentro da biblioteca não forem contadas.
Ari

2

Além disso, se o seu arquivo estiver dentro de um jar, você também poderá usar este:

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

O caminho deve começar, / por exemplo, se o seu jar for

my.jar/com/some/thing/a.txt

Então você deseja invocá-lo assim:

String myTxt = fromFileInJar("/com/com/thing/a.txt");

2

Em uma linha (Java 8), supondo que você tenha um Reader:

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

2

Com base na resposta de @ erickson, você pode usar:

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.