Como ler / converter um InputStream em uma String em Java?

4063

Se você tem um java.io.InputStreamobjeto, como deve processar esse objeto e produzir um String?


Suponha que eu possua um InputStreamque contenha dados de texto e deseje convertê-lo em um String, para que, por exemplo, eu possa gravá-lo em um arquivo de log.

Qual é a maneira mais fácil de obter InputStreame convertê-lo em um String?

public String convertStreamToString(InputStream is) {
    // ???
}
Johnny Maelstrom
fonte
36
As respostas a esta pergunta só funcionam se você quiser ler o conteúdo do fluxo completamente (até que ele seja fechado). Como isso nem sempre é intencional (solicitações de HTTP com uma conexão keep-alive não serão fechadas), esse método chama block (não fornecendo o conteúdo).
F1sh
21
Você precisa conhecer e especificar a codificação de caracteres para o fluxo ou terá erros de codificação, pois estará usando uma codificação escolhida aleatoriamente, dependendo de qual máquina / sistema operacional / plataforma ou versão do seu código é executado. Ou seja, não use métodos que dependam da codificação padrão da plataforma.
Christoffer Hammarström
11
Apenas para me divertir com meu próprio comentário de 9 anos atrás, hoje em dia eu uso "String s = new File (" SomeFile.txt "). Text" do Groovy para ler um arquivo inteiro de uma só vez e funciona muito bem. Estou feliz em usar o groovy para o meu código de não produção (script) e - honestamente, obrigando você a lidar com codificação e arquivos extremamente longos, da mesma forma que o java é uma ótima idéia para o código de produção de qualquer maneira, para que funcione de acordo com seu objetivo, O Groovy funciona para scripts rápidos nos quais o java não é bom - basta usar a ferramenta certa para o trabalho e tudo funciona.
Bill K
Apenas simplificando: ByteArrayOutputStream outputBytes = new ByteArrayOutputStream(); for(byte[] b = new byte[512]; 0 < inputStream.read(b); outputBytes.write(b)); return new String(outputBytes.toByteArray(), StandardCharsets.UTF_8);
Felypp Oliveira
No @BillK com Java 11, você pode usar o String s = Files.readString​(Path.of("SomeFile.txt"));que há de melhor em linguagem, o que nunca suporta conversões de tipo mágico como a que você descreveu.
Holger

Respostas:

2530

Uma boa maneira de fazer isso é usando commons Apache IOUtils para copiar o InputStreamem um StringWriter... algo como

StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();

ou mesmo

// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding); 

Como alternativa, você pode usar ByteArrayOutputStream se não quiser misturar seus Streams e Writers

Harry Lime
fonte
75
Para desenvolvedores de Android, parece que o Android não vem com IOUtils do Apache. Portanto, você pode considerar consultar outras respostas.
precisa saber é o seguinte
47
Esta é uma pergunta incrivelmente antiga neste momento (foi feita em 2008). Vale a pena ler respostas mais modernas. Alguns usam chamadas nativas da biblioteca Java 8.
Shadoninja 28/03
36
Esta resposta está muito desatualizada e deve-se poder marcá-la como tal (infelizmente isso não é possível em ATM).
código é o seguinte
7
IOUtils.toString () há muito tempo foi preterido. Esta resposta definitivamente não é mais a maneira recomendada.
21919 Roshan
7
em seguida, editar -lo para explicar porque é obsoleto para os leitores de ajuda futuros.
Jean-François Fabre
2487

Resuma outras respostas, encontrei 11 maneiras principais de fazer isso (veja abaixo). E eu escrevi alguns testes de desempenho (veja os resultados abaixo):

Maneiras de converter um InputStream em uma String:

  1. Usando IOUtils.toString(Apache Utils)

    String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
  2. Usando CharStreams(Goiaba)

    String result = CharStreams.toString(new InputStreamReader(
          inputStream, Charsets.UTF_8));
  3. Usando Scanner(JDK)

    Scanner s = new Scanner(inputStream).useDelimiter("\\A");
    String result = s.hasNext() ? s.next() : "";
  4. Usando a API de Stream (Java 8). Aviso : Esta solução converte quebras de linha diferentes (como \r\n) em \n.

    String result = new BufferedReader(new InputStreamReader(inputStream))
      .lines().collect(Collectors.joining("\n"));
  5. Utilizando a API de Stream paralela (Java 8). Aviso : Esta solução converte quebras de linha diferentes (como \r\n) em \n.

    String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
       .parallel().collect(Collectors.joining("\n"));
  6. Usando InputStreamReadere StringBuilder(JDK)

    final int bufferSize = 1024;
    final char[] buffer = new char[bufferSize];
    final StringBuilder out = new StringBuilder();
    Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8);
    int charsRead;
    while((charsRead = in.read(buffer, 0, buffer.length)) > 0) {
        out.append(buffer, 0, charsRead);
    }
    return out.toString();
  7. Usando StringWritere IOUtils.copy(Apache Commons)

    StringWriter writer = new StringWriter();
    IOUtils.copy(inputStream, writer, "UTF-8");
    return writer.toString();
  8. Usando ByteArrayOutputStreame inputStream.read(JDK)

    ByteArrayOutputStream result = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length;
    while ((length = inputStream.read(buffer)) != -1) {
        result.write(buffer, 0, length);
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return result.toString("UTF-8");
  9. Usando BufferedReader(JDK). Aviso: Esta solução converte quebras de linha diferentes (como \n\r) na line.separatorpropriedade do sistema (por exemplo, no Windows para "\ r \ n").

    String newLine = System.getProperty("line.separator");
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    StringBuilder result = new StringBuilder();
    boolean flag = false;
    for (String line; (line = reader.readLine()) != null; ) {
        result.append(flag? newLine: "").append(line);
        flag = true;
    }
    return result.toString();
  10. Usando BufferedInputStreame ByteArrayOutputStream(JDK)

    BufferedInputStream bis = new BufferedInputStream(inputStream);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    int result = bis.read();
    while(result != -1) {
        buf.write((byte) result);
        result = bis.read();
    }
    // StandardCharsets.UTF_8.name() > JDK 7
    return buf.toString("UTF-8");
  11. Usando inputStream.read()e StringBuilder(JDK). Aviso : Esta solução tem problemas com Unicode, por exemplo, com texto em russo (funciona corretamente apenas com texto não-Unicode)

    int ch;
    StringBuilder sb = new StringBuilder();
    while((ch = inputStream.read()) != -1)
        sb.append((char)ch);
    reset();
    return sb.toString();

Atenção :

  1. As soluções 4, 5 e 9 convertem quebras de linha diferentes em uma.

  2. A solução 11 não pode funcionar corretamente com texto Unicode

Testes de performance

Testes de desempenho para Stringurl pequeno (comprimento = 175), no github (modo = Tempo médio, sistema = Linux, a pontuação 1.343 é a melhor):

              Benchmark                         Mode  Cnt   Score   Error  Units
 8. ByteArrayOutputStream and read (JDK)        avgt   10   1,343 ± 0,028  us/op
 6. InputStreamReader and StringBuilder (JDK)   avgt   10   6,980 ± 0,404  us/op
10. BufferedInputStream, ByteArrayOutputStream  avgt   10   7,437 ± 0,735  us/op
11. InputStream.read() and StringBuilder (JDK)  avgt   10   8,977 ± 0,328  us/op
 7. StringWriter and IOUtils.copy (Apache)      avgt   10  10,613 ± 0,599  us/op
 1. IOUtils.toString (Apache Utils)             avgt   10  10,605 ± 0,527  us/op
 3. Scanner (JDK)                               avgt   10  12,083 ± 0,293  us/op
 2. CharStreams (guava)                         avgt   10  12,999 ± 0,514  us/op
 4. Stream Api (Java 8)                         avgt   10  15,811 ± 0,605  us/op
 9. BufferedReader (JDK)                        avgt   10  16,038 ± 0,711  us/op
 5. parallel Stream Api (Java 8)                avgt   10  21,544 ± 0,583  us/op

Testes de desempenho para Stringurl grande (comprimento = 50100), no github (modo = Tempo médio, sistema = Linux, a pontuação 200.715 é a melhor):

               Benchmark                        Mode  Cnt   Score        Error  Units
 8. ByteArrayOutputStream and read (JDK)        avgt   10   200,715 ±   18,103  us/op
 1. IOUtils.toString (Apache Utils)             avgt   10   300,019 ±    8,751  us/op
 6. InputStreamReader and StringBuilder (JDK)   avgt   10   347,616 ±  130,348  us/op
 7. StringWriter and IOUtils.copy (Apache)      avgt   10   352,791 ±  105,337  us/op
 2. CharStreams (guava)                         avgt   10   420,137 ±   59,877  us/op
 9. BufferedReader (JDK)                        avgt   10   632,028 ±   17,002  us/op
 5. parallel Stream Api (Java 8)                avgt   10   662,999 ±   46,199  us/op
 4. Stream Api (Java 8)                         avgt   10   701,269 ±   82,296  us/op
10. BufferedInputStream, ByteArrayOutputStream  avgt   10   740,837 ±    5,613  us/op
 3. Scanner (JDK)                               avgt   10   751,417 ±   62,026  us/op
11. InputStream.read() and StringBuilder (JDK)  avgt   10  2919,350 ± 1101,942  us/op

Gráficos (testes de desempenho dependendo do comprimento do fluxo de entrada no sistema Windows 7)
insira a descrição da imagem aqui

Teste de desempenho (tempo médio), dependendo do comprimento do fluxo de entrada no sistema Windows 7:

 length  182    546     1092    3276    9828    29484   58968

 test8  0.38    0.938   1.868   4.448   13.412  36.459  72.708
 test4  2.362   3.609   5.573   12.769  40.74   81.415  159.864
 test5  3.881   5.075   6.904   14.123  50.258  129.937 166.162
 test9  2.237   3.493   5.422   11.977  45.98   89.336  177.39
 test6  1.261   2.12    4.38    10.698  31.821  86.106  186.636
 test7  1.601   2.391   3.646   8.367   38.196  110.221 211.016
 test1  1.529   2.381   3.527   8.411   40.551  105.16  212.573
 test3  3.035   3.934   8.606   20.858  61.571  118.744 235.428
 test2  3.136   6.238   10.508  33.48   43.532  118.044 239.481
 test10 1.593   4.736   7.527   20.557  59.856  162.907 323.147
 test11 3.913   11.506  23.26   68.644  207.591 600.444 1211.545
Viacheslav Vedenin
fonte
17
Ao escrever a "resposta resumida", observe que algumas soluções convertem automaticamente quebras de linha diferentes (como \r\n) nas \nquais podem ser indesejadas em alguns casos. Também seria bom ver a memória adicional necessária ou pelo menos a pressão de alocação (pelo menos você pode executar o JMH -prof gc). Para um post realmente interessante, seria ótimo ver os gráficos (dependendo do comprimento da string dentro do mesmo tamanho de entrada e dependendo do tamanho da entrada dentro do mesmo comprimento de string).
Tagir Valeev
16
Voto a favor; o mais engraçado é que os resultados são mais do que o esperado: deve-se usar o açúcar sintático JDK e / ou Apache Commons padrão.
Aleksei Matiushkin 15/04
25
Post incrível. Só uma coisa. O Java 8 adverte contra o uso de fluxos paralelos em recursos que forçarão você a bloquear e aguardar (como esse fluxo de entrada), para que a opção de fluxo paralelo seja bastante complicada e não valha a pena?
Mangusbrother
10
O fluxo paralelo realmente mantém a ordem das linhas?
Natix 29/09
6
O que é o reset()exemplo 11?
Rob Stewart
2307

Aqui está uma maneira de usar apenas a biblioteca Java padrão (observe que o fluxo não está fechado, sua milhagem pode variar).

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

Aprendi esse truque no artigo "Truques estúpidos do scanner" . A razão pela qual isso funciona é porque o Scanner interage com os tokens no fluxo e, nesse caso, separamos os tokens usando "início do limite de entrada" (\ A), fornecendo apenas um token para todo o conteúdo do fluxo.

Observe que, se você precisar ser específico sobre a codificação do fluxo de entrada, poderá fornecer o segundo argumento ao Scannerconstrutor que indica qual conjunto de caracteres usar (por exemplo, "UTF-8").

A gorjeta do chapéu também vale para Jacob , que uma vez me indicou o referido artigo.

Pavel Repin
fonte
8
Obrigado, pela minha versão disso, adicionei um bloco finalmente que fecha o fluxo de entrada, para que o usuário não precise desde que você terminou de ler a entrada. Simplifica consideravelmente o código do chamador.
4
@PavelRepin @Patrick no meu caso, um inputStream vazio causou um NPE durante a construção do Scanner. Eu tive que adicionar if (is == null) return "";logo no início do método; Acredito que esta resposta precisa ser atualizada para lidar melhor com inputStreams nulos.
CFL_Jeff
115
Para Java 7 pode fechar em um try-com: try(java.util.Scanner s = new java.util.Scanner(is)) { return s.useDelimiter("\\A").hasNext() ? s.next() : ""; }
earcam
5
Infelizmente, essa solução parece perder as exceções geradas na minha implementação de fluxo subjacente.
Taig 16/07/2013
11
Para sua informação, os blocos hasNext nos fluxos de entrada do console (veja aqui ). (Acabei de encontrar este problema no momento.) Caso contrário, esta solução funciona bem ... apenas um aviso.
24714 Ryan
848

O Apache Commons permite:

String myString = IOUtils.toString(myInputStream, "UTF-8");

Obviamente, você pode escolher outras codificações de caracteres além de UTF-8.

Veja também: ( documentação )

Chinnery
fonte
1
Além disso, há um método que aceita apenas um argumento inputStream, se você encontrar a codificação padrão.
Guillaume Coté 03/02
13
@ Guillaume Coté Acho que a mensagem aqui é que você nunca deve ficar "bem com a codificação padrão", pois não pode ter certeza do que é, dependendo da plataforma em que o código java é executado.
Por Wiklander
7
Por Wiklander Não concordo com você. O código que funcionará em um único pode ter certeza de que a codificação padrão será adequada. Para códigos que apenas abrem arquivos locais, é uma opção razoável solicitar que eles sejam codificados na codificação padrão da plataforma.
Guillaume Coté 04/02
39
Para salvar qualquer pessoa do incômodo de pesquisar no Google - <dependência> <groupId> org.apache.commons </groupId> <artifactId> commons-io </artifactId> <versão> 1.3.2 </version> </dependency>
Chris
7
Também pouca melhoria seria usar a constante apache io (ou outra) para codificação de caracteres em vez de usar literal de cadeia simples - por exemplo: IOUtils.toString (myInputStream, Charsets.UTF_8);
300

Levando em conta o arquivo, é preciso primeiro obter uma java.io.Readerinstância. Isso pode ser lido e adicionado a um StringBuilder(não precisamos StringBufferse não estiver acessando-o em vários threads e StringBuilderfor mais rápido). O truque aqui é que trabalhamos em blocos e, como tal, não precisa de outros fluxos de buffer. O tamanho do bloco é parametrizado para otimização do desempenho em tempo de execução.

public static String slurp(final InputStream is, final int bufferSize) {
    final char[] buffer = new char[bufferSize];
    final StringBuilder out = new StringBuilder();
    try (Reader in = new InputStreamReader(is, "UTF-8")) {
        for (;;) {
            int rsz = in.read(buffer, 0, buffer.length);
            if (rsz < 0)
                break;
            out.append(buffer, 0, rsz);
        }
    }
    catch (UnsupportedEncodingException ex) {
        /* ... */
    }
    catch (IOException ex) {
        /* ... */
    }
    return out.toString();
}
Paul de Vrieze
fonte
8
Esta solução usa caracteres multibyte. O exemplo usa a codificação UTF-8 que permite a expressão do intervalo unicode completo (incluindo chinês). Substituir "UTF-8" por outra codificação permitiria que essa codificação fosse usada.
Paul de Vrieze
27
@ Usuário1 - eu gosto de usar bibliotecas no meu código para poder fazer meu trabalho mais rapidamente. É incrível quando seus gerentes dizem "Uau, James! Como você conseguiu isso tão rápido ?!". Mas quando temos que gastar tempo reinventando a roda só porque perdemos idéias sobre a inclusão de um utilitário comum, reutilizável, testado e testado, estamos perdendo tempo que poderíamos estar gastando para promover as metas de nosso projeto. Quando reinventamos a roda, trabalhamos duas vezes mais e chegamos à linha de chegada muito mais tarde. Quando estamos na linha de chegada, não há ninguém para nos parabenizar. Ao construir uma casa, não construir o martelo também
jmort253
10
Desculpe, depois de reler meu comentário, ele sai um pouco arrogante. Eu só acho que é importante ter uma boa razão para bibliotecas de evitar e que a razão é válida, que não poderia muito bem ser :)
jmort253
4
@ jmort253 Observamos uma regressão de desempenho após atualizar algumas bibliotecas em nosso produto por várias vezes. Felizmente, estamos construindo e vendendo nosso próprio produto, para não termos realmente os prazos. Infelizmente, estamos construindo um produto que está disponível em muitas JVMs, bancos de dados e servidores de aplicativos em muitos sistemas operacionais, por isso temos que pensar nos usuários que usam máquinas ruins ... E uma otimização de operação de cadeia pode melhorar o desempenho em 30 a 40%. E uma correção: In our product, I even replaceddeveria ser 'até substituímos'.
Coolcfan
10
@ jmort253 Se você já usaria o apache commons, eu diria, vá em frente. Ao mesmo tempo, há um custo real no uso de bibliotecas (como mostra a proliferação de dependência em muitas bibliotecas apache java). Se esse fosse o único uso da biblioteca, seria um exagero usá-la. Por outro lado, para determinar seu próprio tamanho de buffer, você pode ajustar o saldo de uso de memória / processador.
Paul de Vrieze
248

Usar:

InputStream in = /* Your InputStream */;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String read;

while ((read=br.readLine()) != null) {
    //System.out.println(read);
    sb.append(read);
}

br.close();
return sb.toString();
sampathpremarathna
fonte
11
O problema é que você primeiro se divide em linhas e depois desfaz isso. É mais fácil e rápido ler apenas buffers arbitrários.
Paul de Vrieze
20
Além disso, o readLine não distingue entre \ n e \ r, portanto você não pode reproduzir o fluxo exato novamente.
María Arias de Reyna Domínguez 10/10
2
muito ineficiente, como readLinelido caractere por caractere para procurar EOL. Além disso, se não houver quebra de linha no fluxo, isso realmente não faz sentido.
Njzk2
3
@ Gops AB: Se você tentar fazer isso e sua amostra tiver novas linhas, verá que a maneira como esse loop é construído usando readline () e StringBuilder.append () na verdade não preserva as novas linhas.
Russ Bateman
4
Esta não é a melhor resposta porque não é estritamente byte in byte out. O leitor cria novas linhas, portanto, você deve ter cuidado para mantê-las.
precisa saber é o seguinte
173

Se você estiver usando o Google-Collections / Guava, poderá fazer o seguinte:

InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);

Observe que o segundo parâmetro (ou seja, Charsets.UTF_8) para o InputStreamReadernão é necessário, mas geralmente é uma boa idéia especificar a codificação se você a conhece (o que você deve!)

Sakuraba
fonte
2
@harschware: Dada a pergunta foi: "Se você tem o objeto java.io.InputStream, como deve processar esse objeto e produzir uma String?" Eu assumi que um fluxo já está presente na situação.
Sakuraba
Você não explicou sua resposta muito bem e tinha variáveis ​​estranhas; user359996 disse a mesma coisa que você, mas muito mais claramente.
Uronym
2
+1 para goiaba, -1 para não especificar a codificação do fluxo de entrada. por exemplo. novo InputStreamReader (stream, "UTF-8")
andras
@ Chris Noldus Por outro lado, algumas pessoas já têm goiaba em seu projeto, como eu, e acham que essa solução é mais elegante que a versão somente para sdk.
CorayThan
@Vadzim que a resposta é a mesma que este - ambos CharStreams.toString uso
Tom
125

Esta é a melhor solução Java pura que se encaixa perfeitamente no Android e em qualquer outra JVM.

Esta solução funciona incrivelmente bem ... é simples, rápida e funciona em fluxos pequenos e grandes da mesma forma !! (veja a referência acima .. No. 8 )

public String readFullyAsString(InputStream inputStream, String encoding)
        throws IOException {
    return readFully(inputStream).toString(encoding);
}

public byte[] readFullyAsBytes(InputStream inputStream)
        throws IOException {
    return readFully(inputStream).toByteArray();
}

private ByteArrayOutputStream readFully(InputStream inputStream)
        throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024];
    int length = 0;
    while ((length = inputStream.read(buffer)) != -1) {
        baos.write(buffer, 0, length);
    }
    return baos;
}
TacB0sS
fonte
4
Funciona bem no Android em comparação com outras respostas que funcionam apenas no java corporativo.
vortexwolf
Falhava no Android com o erro OutOfMemory na linha ".write", toda vez, para seqüências curtas.
Adam
Eu adicionei a codificação. apenas como uma observação lateral, o método readFully original que tenho no meu código não retorna String, mas retorna byte [] para uma funcionalidade de propósito mais geral. A implementação da nova String (...) com codificação é de responsabilidade do que usa a API!
TacB0sS
2
Nota rápida: o tamanho da memória é maximizado em 2*nque n é o tamanho do fluxo, conforme o ByteArrayInputStreamsistema de crescimento automático.
Njzk2
3
Dobra desnecessariamente o uso de memória, precioso em dispositivos móveis. É melhor você usar o InputStreamReader e anexá-lo ao StringReader, a conversão de bytes em caracteres será feita em tempo real, não em massa no final.
precisa saber é
84

Para completar, aqui está a solução Java 9 :

public static String toString(InputStream input) throws IOException {
    return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}

O readAllBytesestá atualmente em JDK 9 base de código principal, por isso provável que apareça no comunicado. Você pode experimentá-lo agora mesmo usando as construções de captura instantânea do JDK 9 .

Tagir Valeev
fonte
O método não aloca muita memória para leitura? byte[] buf = new byte[DEFAULT_BUFFER_SIZE];onde o MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;que dá MAX_BUFFER_SIZE = 2147483639. O Google diz que tem cerca de 2,147 GB.
Rekin
Desculpe, cometi um erro nos cálculos. É 2 GB. Eu editei o comentário. Então, mesmo que eu leia como um arquivo de 4kb, uso 2 gb de memória?
Rekin
2
@ChristianHujer, não o vejo no último commit do jdk8u . Os novos métodos AFAIK nunca são introduzidos nas atualizações de Java, apenas nos principais releases.
Tagir Valeev
4
@ChristianHujer, a questão era sobre InputStream, não sobre Path. O InputStreampode ser criado a partir de muitas fontes diferentes, não apenas de arquivos.
Tagir Valeev 02/02
5
Isso foi escrito há um ano, então, para atualizar, confirmo que esse método está realmente no release público JDK 9. Além disso, se sua codificação for "ISO-Latin-1", isso será extremamente eficiente, já que o Java 9 Strings agora usa uma byte[]implementação se todos os caracteres estiverem nos primeiros 256 pontos de código. Isso significa que a nova String (byte [], "ISO-Latin-1") será uma cópia simples da matriz.
Klitos Kyriacou
66

Usar:

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;

public static String readInputStreamAsString(InputStream in)
    throws IOException {

    BufferedInputStream bis = new BufferedInputStream(in);
    ByteArrayOutputStream buf = new ByteArrayOutputStream();
    int result = bis.read();
    while(result != -1) {
      byte b = (byte)result;
      buf.write(b);
      result = bis.read();
    }
    return buf.toString();
}
Jon Moore
fonte
@ DanielDeLeón Não, não. É um BufferedInputStream. As leituras subjacentes são 8192 bytes de cada vez.
Marquês de Lorne
2
@EJP Eu achei mais lento do que usar BufferedInputStream e ler em um buffer de matriz de bytes em vez de um byte por vez. Exemplo: 200ms vs 60ms ao ler um arquivo 4.56 MiB.
Jk7 17/03/19
É estranho que ninguém tenha apontado o outro grande problema aqui (sim, ler o conteúdo byte a byte é um desperdício, mesmo com o buffer): depende do que quer que seja a "codificação padrão" - isso raramente é uma boa maneira. Em vez disso, certifique-se de passar a codificação como argumento para buf.toString().
StaxMan 24/01/19
@ jk7 O tempo para ler um arquivo de 4,56 MB é tão pequeno que as diferenças não podem ter sido significativas.
Marquês de Lorne
63

Aqui está a solução mais elegante e pura de Java (sem biblioteca) que eu criei após algumas experiências:

public static String fromStream(InputStream in) throws IOException
{
    BufferedReader reader = new BufferedReader(new InputStreamReader(in));
    StringBuilder out = new StringBuilder();
    String newLine = System.getProperty("line.separator");
    String line;
    while ((line = reader.readLine()) != null) {
        out.append(line);
        out.append(newLine);
    }
    return out.toString();
}
Drew Noakes
fonte
8
@TorbenKohlmeier, leitores e buffers não precisam ser fechados. O fornecido InputStreamdeve ser fechado pelo chamador.
de Drew Noakes
7
Não se esqueça de mencionar que há um construtor mais preferível no InputStreamReader que usa um CharSet.
jontejj
7
por que as pessoas continuam usando readLine? Se você não usar as linhas por si só, o que é bom (excepto se está muito lento?)
njzk2
4
Não leia por linhas. E se uma linha for tão longa para não caber na pilha?
voho
4
@voho, se uma linha é tão longa, não há como alocar o valor de retorno de qualquer maneira, que deve ser igual ou maior em tamanho a essa linha. Se você estiver lidando com arquivos tão grandes, deverá transmiti-los. Existem muitos casos de uso para carregar pequenos arquivos de texto na memória.
de Drew Noakes
55

Fiz uma comparação com 14 respostas distintas aqui (desculpe por não fornecer créditos, mas há muitas duplicatas).

O resultado é muito surpreendente. Acontece que o Apache IOUtils é o mais lento e ByteArrayOutputStreamas soluções mais rápidas:

Então, primeiro, aqui está o melhor método:

public String inputStreamToString(InputStream inputStream) throws IOException {
    try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
        byte[] buffer = new byte[1024];
        int length;
        while ((length = inputStream.read(buffer)) != -1) {
            result.write(buffer, 0, length);
        }

        return result.toString(UTF_8);
    }
}

Resultados de benchmark, de 20 MB de bytes aleatórios em 20 ciclos

Tempo em milissegundos

  • ByteArrayOutputStreamTest: 194
  • NioStream: 198
  • Java9ISTransferTo: 201
  • Java9ISReadAllBytes: 205
  • BufferedInputStreamVsByteArrayOutputStream: 314
  • ApacheStringWriter2: 574
  • GuavaCharStreams: 589
  • ScannerReaderNoNextTest: 614
  • ScannerReader: 633
  • ApacheStringWriter: 1544
  • StreamApi: erro
  • ParallelStreamApi: erro
  • BufferReaderTest: erro
  • InputStreamAndStringBuilder: Erro

Código fonte de referência

import com.google.common.io.CharStreams;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * Created by Ilya Gazman on 2/13/18.
 */
public class InputStreamToString {


    private static final String UTF_8 = "UTF-8";

    public static void main(String... args) {
        log("App started");
        byte[] bytes = new byte[1024 * 1024];
        new Random().nextBytes(bytes);
        log("Stream is ready\n");

        try {
            test(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void test(byte[] bytes) throws IOException {
        List<Stringify> tests = Arrays.asList(
                new ApacheStringWriter(),
                new ApacheStringWriter2(),
                new NioStream(),
                new ScannerReader(),
                new ScannerReaderNoNextTest(),
                new GuavaCharStreams(),
                new StreamApi(),
                new ParallelStreamApi(),
                new ByteArrayOutputStreamTest(),
                new BufferReaderTest(),
                new BufferedInputStreamVsByteArrayOutputStream(),
                new InputStreamAndStringBuilder(),
                new Java9ISTransferTo(),
                new Java9ISReadAllBytes()
        );

        String solution = new String(bytes, "UTF-8");

        for (Stringify test : tests) {
            try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
                String s = test.inputStreamToString(inputStream);
                if (!s.equals(solution)) {
                    log(test.name() + ": Error");
                    continue;
                }
            }
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 20; i++) {
                try (ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes)) {
                    test.inputStreamToString(inputStream);
                }
            }
            log(test.name() + ": " + (System.currentTimeMillis() - startTime));
        }
    }

    private static void log(String message) {
        System.out.println(message);
    }

    interface Stringify {
        String inputStreamToString(InputStream inputStream) throws IOException;

        default String name() {
            return this.getClass().getSimpleName();
        }
    }

    static class ApacheStringWriter implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            StringWriter writer = new StringWriter();
            IOUtils.copy(inputStream, writer, UTF_8);
            return writer.toString();
        }
    }

    static class ApacheStringWriter2 implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            return IOUtils.toString(inputStream, UTF_8);
        }
    }

    static class NioStream implements Stringify {

        @Override
        public String inputStreamToString(InputStream in) throws IOException {
            ReadableByteChannel channel = Channels.newChannel(in);
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 16);
            ByteArrayOutputStream bout = new ByteArrayOutputStream();
            WritableByteChannel outChannel = Channels.newChannel(bout);
            while (channel.read(byteBuffer) > 0 || byteBuffer.position() > 0) {
                byteBuffer.flip();  //make buffer ready for write
                outChannel.write(byteBuffer);
                byteBuffer.compact(); //make buffer ready for reading
            }
            channel.close();
            outChannel.close();
            return bout.toString(UTF_8);
        }
    }

    static class ScannerReader implements Stringify {

        @Override
        public String inputStreamToString(InputStream is) throws IOException {
            java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
            return s.hasNext() ? s.next() : "";
        }
    }

    static class ScannerReaderNoNextTest implements Stringify {

        @Override
        public String inputStreamToString(InputStream is) throws IOException {
            java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
            return s.next();
        }
    }

    static class GuavaCharStreams implements Stringify {

        @Override
        public String inputStreamToString(InputStream is) throws IOException {
            return CharStreams.toString(new InputStreamReader(
                    is, UTF_8));
        }
    }

    static class StreamApi implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            return new BufferedReader(new InputStreamReader(inputStream))
                    .lines().collect(Collectors.joining("\n"));
        }
    }

    static class ParallelStreamApi implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            return new BufferedReader(new InputStreamReader(inputStream)).lines()
                    .parallel().collect(Collectors.joining("\n"));
        }
    }

    static class ByteArrayOutputStreamTest implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            try(ByteArrayOutputStream result = new ByteArrayOutputStream()) {
                byte[] buffer = new byte[1024];
                int length;
                while ((length = inputStream.read(buffer)) != -1) {
                    result.write(buffer, 0, length);
                }

                return result.toString(UTF_8);
            }
        }
    }

    static class BufferReaderTest implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            String newLine = System.getProperty("line.separator");
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder result = new StringBuilder(UTF_8);
            String line;
            boolean flag = false;
            while ((line = reader.readLine()) != null) {
                result.append(flag ? newLine : "").append(line);
                flag = true;
            }
            return result.toString();
        }
    }

    static class BufferedInputStreamVsByteArrayOutputStream implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            BufferedInputStream bis = new BufferedInputStream(inputStream);
            ByteArrayOutputStream buf = new ByteArrayOutputStream();
            int result = bis.read();
            while (result != -1) {
                buf.write((byte) result);
                result = bis.read();
            }

            return buf.toString(UTF_8);
        }
    }

    static class InputStreamAndStringBuilder implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            int ch;
            StringBuilder sb = new StringBuilder(UTF_8);
            while ((ch = inputStream.read()) != -1)
                sb.append((char) ch);
            return sb.toString();
        }
    }

    static class Java9ISTransferTo implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            inputStream.transferTo(bos);
            return bos.toString(UTF_8);
        }
    }

    static class Java9ISReadAllBytes implements Stringify {

        @Override
        public String inputStreamToString(InputStream inputStream) throws IOException {
            return new String(inputStream.readAllBytes(), UTF_8);
        }
    }

}
Ilya Gazman
fonte
Fazer benchmarks em Java não é fácil (principalmente por causa do JIT). Depois de ler o código-fonte do Benchmark, estou convencido de que esses valores acima não são precisos e todos devem ter cuidado ao acreditar neles.
Dalibor
@ Dalibor, você provavelmente deve fornecer mais argumentos para sua reivindicação, em vez de apenas um link.
Ilya Gazman 28/05/19
Eu acho que é fato muito conhecido que não é fácil fazer seu próprio benchmark. Para aqueles que não sabem que, há ligação;)
Dalibor
@ Dalibor Talvez eu não seja o melhor, mas tenho um bom entendimento dos benchmarks Java, portanto, a menos que você possa apontar um problema específico, você é enganoso e não continuarei a conversa com você nessas condições.
Ilya Gazman 29/05/19
Concordo principalmente com Dalibor. Você diz ter um "bom entendimento dos benchmarks de Java", mas parece ter implementado a abordagem mais ingênua e aparentemente ignorante dos problemas conhecidos dessa abordagem. Para iniciantes, leia todos os posts sobre esta questão: stackoverflow.com/questions/504103/… #
18119 DavidS
41

Eu usaria alguns truques do Java 8.

public static String streamToString(final InputStream inputStream) throws Exception {
    // buffering optional
    try
    (
        final BufferedReader br
           = new BufferedReader(new InputStreamReader(inputStream))
    ) {
        // parallel optional
        return br.lines().parallel().collect(Collectors.joining("\n"));
    } catch (final IOException e) {
        throw new RuntimeException(e);
        // whatever.
    }
}

Essencialmente, o mesmo que algumas outras respostas, exceto mais sucintas.

Simon Kuang
fonte
5
Isso seria return nullchamado? Os br.lines...retornos ou uma exceção são lançados.
Holloway
3
@Khaled A Khunaifer: sim, com certeza ... talvez você deva dar uma olhada aqui: docs.oracle.com/javase/tutorial/essential/exceptions/… . O que você editou incorretamente é uma instrução "try-with-resources".
jamp
11
Por que você liga parallel()para o stream?
robinst
4
Isso não resultaria em um honesto cópia dos dados se o fluxo de fonte utilizada finais de linha janelas como tudo \r\niria acabar ficando convertido em \n...
Lucas
2
Você pode usar System.lineSeparator()para usar o final de linha dependente da plataforma apropriado.
Steve K
34

Fiz alguns testes de tempo porque o tempo importa sempre.

Tentei obter a resposta em uma String 3 de maneiras diferentes. (mostrado abaixo)
Eu deixei de fora os blocos try / catch para facilitar a leitura.

Para dar contexto, este é o código anterior para todas as três abordagens:

   String response;
   String url = "www.blah.com/path?key=value";
   GetMethod method = new GetMethod(url);
   int status = client.executeMethod(method);

1)

 response = method.getResponseBodyAsString();

2)

InputStream resp = method.getResponseBodyAsStream();
InputStreamReader is=new InputStreamReader(resp);
BufferedReader br=new BufferedReader(is);
String read = null;
StringBuffer sb = new StringBuffer();
while((read = br.readLine()) != null) {
    sb.append(read);
}
response = sb.toString();

3)

InputStream iStream  = method.getResponseBodyAsStream();
StringWriter writer = new StringWriter();
IOUtils.copy(iStream, writer, "UTF-8");
response = writer.toString();

Portanto, depois de executar 500 testes em cada abordagem com os mesmos dados de solicitação / resposta, aqui estão os números. Mais uma vez, essas são minhas descobertas e suas descobertas podem não ser exatamente as mesmas, mas escrevi isso para dar uma indicação a outros das diferenças de eficiência dessas abordagens.

Classificações:
Abordagem nº 1
Abordagem nº 3 - 2,6% mais lento que nº 1
Abordagem nº 2 - 4,3% mais lento que nº 1

Qualquer uma dessas abordagens é uma solução apropriada para obter uma resposta e criar uma String a partir dela.

Brett Holt
fonte
2
2) contém um erro, ele sempre adiciona "nulo" no final da string, pois você está sempre dando mais um passo do que o necessário. O desempenho será o mesmo de qualquer maneira, eu acho. Isso deve funcionar: String read = null; StringBuffer sb = novo StringBuffer (); while ((ler = br.readLine ())! = nulo) {sb.append (ler); }
LukeSolar
Deve-se notar que GetMethod é uma parte da org.apache.commons.httpclient, não padrão Java
jk7
Método # 2 vai consumir o '\ n' se o arquivo tem muitas linhas, isso não deve ser a resposta
Ninja
33

Solução Java pura usando Stream s, funciona desde o Java 8.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

// ...
public static String inputStreamToString(InputStream is) throws IOException {
    try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
        return br.lines().collect(Collectors.joining(System.lineSeparator()));
    }
}

Como mencionado por Christoffer Hammarström abaixo de outras respostas , é mais seguro especificar explicitamente o Charset . Ou seja, o construtor InputStreamReader pode ser alterado da seguinte maneira:

new InputStreamReader(is, Charset.forName("UTF-8"))
Czerny
fonte
11
Em vez de fazer Charset.forName("UTF-8"), use StandardCharsets.UTF_8(de java.nio.charset).
robinst
26

Aqui está a resposta mais ou menos do sampath, limpa um pouco e representada como uma função:

String streamToString(InputStream in) throws IOException {
  StringBuilder out = new StringBuilder();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  for(String line = br.readLine(); line != null; line = br.readLine()) 
    out.append(line);
  br.close();
  return out.toString();
}
TKH
fonte
24

Se você estava se sentindo aventureiro, pode misturar Scala e Java e acabar com isso:

scala.io.Source.fromInputStream(is).mkString("")

A combinação de bibliotecas e códigos Java e Scala tem seus benefícios.

Veja a descrição completa aqui: Maneira linguística de converter um InputStream em uma String no Scala

Jack
fonte
3
Hoje em dia simplesmente isso funciona bem:Source.fromInputStream(...).mkString
KajMagnus
21

Se você não pode usar o Commons IO (FileUtils / IOUtils / CopyUtils), veja um exemplo usando um BufferedReader para ler o arquivo linha por linha:

public class StringFromFile {
    public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
        InputStream is = StringFromFile.class.getResourceAsStream("file.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(is/*, "UTF-8"*/));
        final int CHARS_PER_PAGE = 5000; //counting spaces
        StringBuilder builder = new StringBuilder(CHARS_PER_PAGE);
        try {
            for(String line=br.readLine(); line!=null; line=br.readLine()) {
                builder.append(line);
                builder.append('\n');
            }
        } 
        catch (IOException ignore) { }

        String text = builder.toString();
        System.out.println(text);
    }
}

Ou, se você quiser velocidade bruta, proponho uma variação do que Paul de Vrieze sugeriu (o que evita o uso de um StringWriter (que usa um StringBuffer internamente)):

public class StringFromFileFast {
    public static void main(String[] args) /*throws UnsupportedEncodingException*/ {
        InputStream is = StringFromFileFast.class.getResourceAsStream("file.txt");
        InputStreamReader input = new InputStreamReader(is/*, "UTF-8"*/);
        final int CHARS_PER_PAGE = 5000; //counting spaces
        final char[] buffer = new char[CHARS_PER_PAGE];
        StringBuilder output = new StringBuilder(CHARS_PER_PAGE);
        try {
            for(int read = input.read(buffer, 0, buffer.length);
                    read != -1;
                    read = input.read(buffer, 0, buffer.length)) {
                output.append(buffer, 0, read);
            }
        } catch (IOException ignore) { }

        String text = output.toString();
        System.out.println(text);
    }
}
DJDaveMark
fonte
A fim de fazer o seu trabalho de código, eu tive que usar this.getClass () getClassLoader () getResourceAsStream () (usando Eclipse com um projeto Maven)..
Greuze
19

Este é legal porque:

  • Ele lida com segurança com o Charset.
  • Você controla o tamanho do buffer de leitura.
  • Você pode provisionar o comprimento do construtor e ele não precisa ser um valor exato.
  • Está livre de dependências da biblioteca.
  • É para Java 7 ou superior.

Como fazer isso?

public static String convertStreamToString(InputStream is) throws IOException {
   StringBuilder sb = new StringBuilder(2048); // Define a size if you have an idea of it.
   char[] read = new char[128]; // Your buffer size.
   try (InputStreamReader ir = new InputStreamReader(is, StandardCharsets.UTF_8)) {
     for (int i; -1 != (i = ir.read(read)); sb.append(read, 0, i));
   }
   return sb.toString();
}

Para JDK 9

public static String inputStreamString(InputStream inputStream) throws IOException {
    try (inputStream) {
        return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
    }
}
Daniel De León
fonte
1
O catch (Throwable)realmente não deve estar vazio se este é o código de produção.
Christian Hujer
1
o que colocar nessa declaração catch - throwable?
18719 alex
Embora o uso de UTF-8 seja geralmente razoável, você não deve assumir que os caracteres são codificados dessa maneira.
Martin
18

Esta é uma resposta adaptada do org.apache.commons.io.IOUtils código-fonte para quem deseja ter a implementação do apache, mas não deseja a biblioteca inteira.

private static final int BUFFER_SIZE = 4 * 1024;

public static String inputStreamToString(InputStream inputStream, String charsetName)
        throws IOException {
    StringBuilder builder = new StringBuilder();
    InputStreamReader reader = new InputStreamReader(inputStream, charsetName);
    char[] buffer = new char[BUFFER_SIZE];
    int length;
    while ((length = reader.read(buffer)) != -1) {
        builder.append(buffer, 0, length);
    }
    return builder.toString();
}
Hai Zhang
fonte
18

Certifique-se de fechar os fluxos no final se você usar leitores de fluxo

private String readStream(InputStream iStream) throws IOException {
    //build a Stream Reader, it can read char by char
    InputStreamReader iStreamReader = new InputStreamReader(iStream);
    //build a buffered Reader, so that i can read whole line at once
    BufferedReader bReader = new BufferedReader(iStreamReader);
    String line = null;
    StringBuilder builder = new StringBuilder();
    while((line = bReader.readLine()) != null) {  //Read till end
        builder.append(line);
        builder.append("\n"); // append new line to preserve lines
    }
    bReader.close();         //close all opened stuff
    iStreamReader.close();
    //iStream.close(); //EDIT: Let the creator of the stream close it!
                       // some readers may auto close the inner stream
    return builder.toString();
}

EDIT: No JDK 7+, você pode usar a construção try-with-resources.

/**
 * Reads the stream into a string
 * @param iStream the input stream
 * @return the string read from the stream
 * @throws IOException when an IO error occurs
 */
private String readStream(InputStream iStream) throws IOException {

    //Buffered reader allows us to read line by line
    try (BufferedReader bReader =
                 new BufferedReader(new InputStreamReader(iStream))){
        StringBuilder builder = new StringBuilder();
        String line;
        while((line = bReader.readLine()) != null) {  //Read till end
            builder.append(line);
            builder.append("\n"); // append new line to preserve lines
        }
        return builder.toString();
    }
}
Thamme Gowda
fonte
2
Você está certo sobre o fechamento de fluxos, no entanto, a responsabilidade de fechar fluxos geralmente é do construtor de fluxos (conclua o que você iniciar). Portanto, iStreamrealmente deve ser fechado pelo chamador porque ele foi criado iStream. Além disso, os fluxos de fechamento devem ser feitos em um finallybloco ou, melhor ainda, em uma instrução try 7 com recursos do Java 7. No seu código, quando readLine()lança IOExceptionou builder.append()lança OutOfMemoryError, os fluxos permaneceriam abertos.
Christian Hujer
16

Outro, para todos os usuários do Spring:

import java.nio.charset.StandardCharsets;
import org.springframework.util.FileCopyUtils;

public String convertStreamToString(InputStream is) throws IOException { 
    return new String(FileCopyUtils.copyToByteArray(is), StandardCharsets.UTF_8);
}

Os métodos utilitários in org.springframework.util.StreamUtilssão semelhantes aos métodos in FileCopyUtils, mas deixam o fluxo aberto quando concluído.

James
fonte
16

Use o java.io.InputStream.transferTo (OutputStream) suportado no Java 9 e o ByteArrayOutputStream.toString (String) que recebe o nome do conjunto de caracteres:

public static String gobble(InputStream in, String charsetName) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    in.transferTo(bos);
    return bos.toString(charsetName);
}
jmehrens
fonte
O que você passou pelo nome do conjunto de caracteres no seu caso?
Virsha #
1
@virsha Você precisa determinar isso da fonte que forneceu o InputStream. Lembre -se de que não faz sentido ter uma string sem saber qual codificação ela usa.
precisa saber é o seguinte
15

Aqui está o método completo para converter InputStreamem Stringsem usar nenhuma biblioteca de terceiros. Use StringBuilderpara ambiente de thread único, caso contrário, use StringBuffer.

public static String getString( InputStream is) throws IOException {
    int ch;
    StringBuilder sb = new StringBuilder();
    while((ch = is.read()) != -1)
        sb.append((char)ch);
    return sb.toString();
}
laksys
fonte
3
Nesse método, não há codificação aplicada. Então, digamos que os dados recebidos do InputStream sejam codificados usando UTF-8, a saída estará errada. Para consertar isso, você pode usar in = new InputStreamReader(inputStream)e (char)in.read().
Frederic Leitenberger
2
e ineficiente de memória também; Eu acredito que eu tentei usar isso antes em uma entrada grande e StringBuilder ficou sem memória
gengkev
1
Há outra resposta semelhante que usa um buffer char [] e é mais eficiente e cuida do charset.
Guillaume Perrot
14

Veja como fazer isso usando apenas o JDK usando buffers de matriz de bytes. É assim IOUtils.copy()que todos os métodos commons-io funcionam. Você pode substituir byte[]por char[]se estiver copiando de um em Readervez de um InputStream.

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

...

InputStream is = ....
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
byte[] buffer = new byte[8192];
int count = 0;
try {
  while ((count = is.read(buffer)) != -1) {
    baos.write(buffer, 0, count);
  }
}
finally {
  try {
    is.close();
  }
  catch (Exception ignore) {
  }
}

String charset = "UTF-8";
String inputStreamAsString = baos.toString(charset);
Matt Shannon
fonte
1
Por favor, descreva o que você está tentando realizar.
Ragunath Jawahar
14

Os usuários do Kotlin simplesmente fazem:

println(InputStreamReader(is).readText())

enquanto que

readText()

é o método de extensão interno da biblioteca padrão Kotlin.

Alex
fonte
Na verdade, isso não está muito correto porque não fecha o fluxo. Eu recomendo is.bufferedReader().use { it.readText() }.
Max
9

A maneira mais fácil no JDK é com os seguintes snipplets de código.

String convertToString(InputStream in){
    String resource = new Scanner(in).useDelimiter("\\Z").next();
    return resource;
}
Raghu K Nair
fonte
7

Aqui está minha solução baseada em Java 8 , que usa a nova API de fluxo para coletar todas as linhas de InputStream:

public static String toString(InputStream inputStream) {
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(inputStream));
    return reader.lines().collect(Collectors.joining(
        System.getProperty("line.separator")));
}
Christian Rädel
fonte
1
Parece que você realmente não leu todas as respostas postadas antes. A versão da API de fluxo já estava aqui pelo menos duas vezes .
Tagir Valeev
Eu olhei para todas as soluções, mas não achei adequado. Acho que duas linhas com uma breve descrição são apresentadas com precisão. O try-catch-block da outra solução nunca é usado, por exemplo. Mas você está certo. Com tantas respostas eu mudei para-fast-pular ler-mode ... :-)
Christian Radel
1
Você não está lendo o arquivo original, está convertendo quaisquer finais de linha que o arquivo tenha para quaisquer finais de linha que o SO possua, possivelmente alterando o conteúdo do arquivo.
Christian Hujer
7

Em termos de reduce, e concatpode ser expresso em Java 8 como:

String fromFile = new BufferedReader(new   
InputStreamReader(inputStream)).lines().reduce(String::concat).get();
libnull-dev
fonte
1
Será incrivelmente lento.
Tagir Valeev 21/01
Interessante, por que? Você poderia elaborar?
Libnull-dev 21/01
1
você não sabe por que concatenar seqüências de caracteres em loop em vez de usar StringBuilder é uma má idéia?
Tagir Valeev
Você está certo. StringBuilderpode ser mais eficiente. Vou verificar, mas meu objetivo era mostrar uma abordagem mais funcional com imutável String.
Libnull-dev 26/01
As abordagens funcionais são legais, mas geralmente muito ineficientes.
Lluis Martinez
4

Resposta JDK 7/8 que fecha o fluxo e ainda gera uma IOException:

StringBuilder build = new StringBuilder();
byte[] buf = new byte[1024];
int length;
try (InputStream is = getInputStream()) {
  while ((length = is.read(buf)) != -1) {
    build.append(new String(buf, 0, length));
  }
}
Brian Pontarelli
fonte