Java InputStream en chaîne

1. Vue d'ensemble

Dans ce didacticiel, nous verrons comment convertir un InputStream en String , à l'aide de Guava, de la bibliothèque Apache Commons IO et de Java brut.

Cet article fait partie de la série «Java - Back to Basic» ici sur Baeldung.

2. Conversion avec de la goyave

Commençons par un exemple de Guava - tirant parti de la fonctionnalité 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)); }

Passons en revue les étapes:

  • d' abord - nous terminerons notre InputStream un ByteSource - et pour autant que je sache, c'est la meilleure façon de le faire
  • puis - nous voyons notre ByteSource comme CharSource avec un jeu de caractères UTF8.
  • enfin - nous utilisons le CharSource pour le lire comme une chaîne.

Une façon plus simple de faire la conversion avec Guava , mais le flux doit être explicitement fermé; heureusement, nous pouvons simplement utiliser la syntaxe try-with-resources pour s'en occuper:

@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. Conversion avec Apache Commons IO

Voyons maintenant comment faire cela avec la bibliothèque Commons IO.

Une mise en garde importante ici est que - contrairement à Guava - aucun de ces exemples ne fermera l' InputStream - c'est pourquoi je préfère personnellement la solution 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)); }

Nous pouvons également utiliser un StringWriter pour effectuer la conversion:

@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. Conversion avec Java - InputStream

Regardons maintenant une approche de niveau inférieur utilisant Java ordinaire - un InputStream et un simple 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. Utilisation de Java 8

Java 8 apporte une nouvelle méthode lines () au BufferedReader . Voyons comment nous pouvons l'utiliser pour convertir un InputStream en String:

@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)); }

Il est important de mentionner que lines () utilise la méthode readLine () sous le capot. readLine () suppose qu'une ligne se termine par l'un des sauts de ligne («\ n»), un retour chariot («\ r») ou un retour chariot suivi immédiatement d'un saut de ligne. En d'autres termes, il prend en charge tous les styles de fin de ligne courants - Unix, Windows et même l'ancien Mac OS.

D'un autre côté, lorsque nous utilisons Collectors.joining () , nous devons explicitement décider quel type d'EOL nous voulons utiliser pour la chaîne créée .

Nous pourrions également utiliser Collectors.joining (System.lineSeparator ()) , auquel cas la sortie dépend des paramètres système.

5. Conversion avec Java et un scanner

Ensuite - regardons un exemple Java simple - en utilisant un scanner de texte 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)); }

Notez que le InputStream va être fermé par la fermeture du scanner .

Cela vaut également la peine de clarifier ce que fait useDelimiter («\\ A») . Ici, nous avons passé le '\ A' qui est une expression régulière de marqueur de frontière qui indique le début de l'entrée. Essentiellement, cela signifie que l' appel next () lit tout le flux d'entrée.

La seule raison pour laquelle il s'agit d'un exemple Java 7, et non Java 5, est l'utilisation de l' instruction try-with-resources - transformer cela en un bloc try-finally standard se compilera très bien avec Java 5 .

6. Conversion à l'aide de ByteArrayOutputStream

Enfin, regardons un autre exemple Java simple, cette fois en utilisant 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)); }

Dans cet exemple, tout d'abord, InputStream est converti en ByteArrayOutputStream en lisant et en écrivant des blocs d'octets, puis OutputStream est transformé en un tableau d'octets, qui est utilisé pour créer une chaîne .

7. Conversion avec java.nio

Une autre solution consiste à copier le contenu de InputStream dans un fichier, puis à le convertir en String:

@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)); }

Ici, nous utilisons la classe java.nio.file.Files pour créer un fichier temporaire, ainsi que pour copier le contenu de InputStream dans le fichier. Ensuite, la même classe est utilisée pour convertir le contenu du fichier en String avec la méthode readAllBytes () .

8. Conclusion

Après avoir compilé la meilleure façon de faire la conversion simple - InputStream en String - d'une manière correcte et lisible - et après avoir vu tant de réponses et de solutions extrêmement différentes - je pense qu'une meilleure pratique claire et concise est nécessaire .

L'implémentation de tous ces exemples et extraits de code peut être trouvée sur GitHub - il s'agit d'un projet basé sur Maven, il devrait donc être facile à importer et à exécuter tel quel.