Java InputStream su String

1. Panoramica

In questo tutorial vedremo come convertire un InputStream in una stringa , utilizzando Guava, la libreria Apache Commons IO e Java semplice.

Questo articolo fa parte della serie "Java - Back to Basic" qui su Baeldung.

2. Conversione con Guava

Cominciamo con un esempio Guava, sfruttando la funzionalità ByteSource :

@Test public void givenUsingGuava_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); ByteSource byteSource = new ByteSource() { @Override public InputStream openStream() throws IOException { return inputStream; } }; String text = byteSource.asCharSource(Charsets.UTF_8).read(); assertThat(text, equalTo(originalString)); }

Esaminiamo i passaggi:

  • prima - ci avvolgono il nostro InputStream un bytesource - e per quanto io sappia, questo è il modo più semplice per farlo
  • quindi - vediamo il nostro ByteSource come CharSource con un set di caratteri UTF8.
  • infine , usiamo CharSource per leggerlo come String.

Un modo più semplice per eseguire la conversione con Guava , ma il flusso deve essere chiuso esplicitamente; fortunatamente, possiamo semplicemente usare la sintassi try-with-resources per occuparci di questo:

@Test public void givenUsingGuavaAndJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); String text = null; try (Reader reader = new InputStreamReader(inputStream)) { text = CharStreams.toString(reader); } assertThat(text, equalTo(originalString)); }

3. Conversione con Apache Commons IO

Vediamo ora come farlo con la libreria Commons IO.

Un avvertimento importante qui è che, a differenza di Guava, nessuno di questi esempi chiuderà InputStream , motivo per cui personalmente preferisco la soluzione Guava.

@Test public void givenUsingCommonsIo_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); String text = IOUtils.toString(inputStream, StandardCharsets.UTF_8.name()); assertThat(text, equalTo(originalString)); }

Possiamo anche usare uno StringWriter per eseguire la conversione:

@Test public void givenUsingCommonsIoWithCopy_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); StringWriter writer = new StringWriter(); String encoding = StandardCharsets.UTF_8.name(); IOUtils.copy(inputStream, writer, encoding); assertThat(writer.toString(), equalTo(originalString)); }

4. Conversione con Java - InputStream

Diamo ora un'occhiata a un approccio di livello inferiore utilizzando Java semplice: un InputStream e un semplice StringBuilder :

@Test public void givenUsingJava5_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(DEFAULT_SIZE); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); StringBuilder textBuilder = new StringBuilder(); try (Reader reader = new BufferedReader(new InputStreamReader (inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { int c = 0; while ((c = reader.read()) != -1) { textBuilder.append((char) c); } } assertEquals(textBuilder.toString(), originalString); }

4.1. Utilizzando Java 8

Java 8 introduce un nuovo metodo lines () nel BufferedReader . Vediamo come possiamo utilizzarlo per convertire un InputStream in una stringa:

@Test public void givenUsingJava8_whenConvertingAnInputStreamToAString_thenCorrect() { String originalString = randomAlphabetic(DEFAULT_SIZE); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); String text = new BufferedReader( new InputStreamReader(inputStream, StandardCharsets.UTF_8))) .lines() .collect(Collectors.joining("\n")); assertThat(text, equalTo(originalString)); }

È importante ricordare che lines () utilizza il metodo readLine () sotto il cofano. readLine () presuppone che una riga sia terminata da uno qualsiasi di un avanzamento riga ("\ n"), un ritorno a capo ("\ r") o un ritorno a capo seguito immediatamente da un avanzamento riga. In altre parole, supporta tutti gli stili End Of Line comuni : Unix, Windows e persino il vecchio Mac OS.

D'altra parte, quando usiamo Collectors.joining () , dobbiamo decidere esplicitamente quale tipo di EOL vogliamo usare per la stringa creata .

Potremmo anche usare Collectors.joining (System.lineSeparator ()) , nel qual caso l'output dipende dalle impostazioni di sistema.

5. Conversione con Java e uno scanner

Successivamente, diamo un'occhiata a un semplice esempio Java, utilizzando uno scanner di testo standard :

@Test public void givenUsingJava7_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); String text = null; try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { text = scanner.useDelimiter("\\A").next(); } assertThat(text, equalTo(originalString)); }

Notare che InputStream verrà chiuso alla chiusura dello Scanner .

Vale anche la pena chiarire cosa fa useDelimiter ("\\ A") . Qui, abbiamo passato la "\ A" che è un'espressione regolare del marker di confine che indica l'inizio dell'input. In sostanza, questo significa che la chiamata next () legge l'intero flusso di input.

L'unico motivo per cui questo è un esempio di Java 7, e non di Java 5, è l'uso dell'istruzione try-with-resources : trasformarlo in un blocco try-finalmente standard verrà compilato perfettamente con Java 5 .

6. Conversione tramite ByteArrayOutputStream

Infine, diamo un'occhiata a un altro semplice esempio Java, questa volta utilizzando la classe ByteArrayOutputStream :

@Test public void givenUsingPlainJava_whenConvertingAnInputStreamToString_thenCorrect() throws IOException { String originalString = randomAlphabetic(8); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); byte[] byteArray = buffer.toByteArray(); String text = new String(byteArray, StandardCharsets.UTF_8); assertThat(text, equalTo(originalString)); }

In questo esempio, in primo luogo, InputStream viene convertito in ByteArrayOutputStream leggendo e scrivendo blocchi di byte, quindi OutputStream viene trasformato in una matrice di byte, che viene utilizzata per creare una stringa .

7. Conversione con java.nio

Un'altra soluzione è copiare il contenuto di InputStream in un file, quindi convertirlo in una stringa:

@Test public void givenUsingTempFile_whenConvertingAnInputStreamToAString_thenCorrect() throws IOException { String originalString = randomAlphabetic(DEFAULT_SIZE); InputStream inputStream = new ByteArrayInputStream(originalString.getBytes()); Path tempFile = Files.createTempDirectory("").resolve(UUID.randomUUID().toString() + ".tmp"); Files.copy(inputStream, tempFile, StandardCopyOption.REPLACE_EXISTING); String result = new String(Files.readAllBytes(tempFile)); assertThat(result, equalTo(originalString)); }

Qui, stiamo usando la classe java.nio.file.Files per creare un file temporaneo, oltre a copiare il contenuto di InputStream nel file. Quindi, la stessa classe viene utilizzata per convertire il contenuto del file in una stringa con il metodo readAllBytes () .

8. Conclusione

Dopo aver compilato il modo migliore per eseguire la semplice conversione - InputStream in String - in modo corretto e leggibile - e dopo aver visto così tante risposte e soluzioni estremamente diverse - penso che sia necessaria una best practice chiara e concisa per questo .

L'implementazione di tutti questi esempi e frammenti di codice può essere trovata su GitHub : questo è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.