Si vous avez un objet Java.io.InputStream
, comment devriez-vous traiter cet objet et générer une String
?
Supposons que je possède une InputStream
contenant des données texte et que je souhaite la convertir en String
. Ainsi, je peux par exemple l'écrire dans un fichier journal.
Quel est le moyen le plus simple de convertir InputStream
en String
?
public String convertStreamToString(InputStream is) {
// ???
}
Une bonne façon de faire est d’utiliser Apache commonsIOUtils
pour copier la InputStream
dans une StringWriter
... quelque chose comme:
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();
ou même
// NB: does not close inputStream, you'll have to use try-with-resources for that
String theString = IOUtils.toString(inputStream, encoding);
Sinon, vous pouvez utiliser ByteArrayOutputStream
si vous ne voulez pas mélanger vos flux et écrivains.
Voici un moyen d'utiliser uniquement la bibliothèque Java standard (notez que le flux n'est pas fermé, votre kilométrage peut varier).
static String convertStreamToString(Java.io.InputStream is) {
Java.util.Scanner s = new Java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
J'ai appris cette astuce de "Astuces stupides de scanner" article. Cela fonctionne parce que Scanner effectue une itération sur les jetons du flux. Dans ce cas, nous séparons les jetons en utilisant "début de la limite d'entrée" (\ A), ce qui nous donne un seul jeton pour tout le contenu du courant.
Remarque: si vous devez spécifier le codage du flux d'entrée, vous pouvez fournir au constructeur Scanner
le deuxième argument qui indique le jeu de caractères à utiliser (par exemple, "UTF-8").
La pointe du chapeau va également à Jacob , qui m'a une fois dirigé vers ledit article.
Résumez les autres réponses. J'ai trouvé 11 façons principales de le faire (voir ci-dessous). Et j'ai écrit quelques tests de performance (voir les résultats ci-dessous):
Moyens de convertir un InputStream en String:
Utilisation de IOUtils.toString
(Apache Utils)
String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
Utilisation de CharStreams
(goyave)
String result = CharStreams.toString(new InputStreamReader(
inputStream, Charsets.UTF_8));
Utilisation de Scanner
(JDK)
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String result = s.hasNext() ? s.next() : "";
Utilisation de Stream API (Java 8). Warning: cette solution convertit différents sauts de ligne (comme \r\n
) en \n
.
String result = new BufferedReader(new InputStreamReader(inputStream))
.lines().collect(Collectors.joining("\n"));
Utilisation de parallel Stream API (Java 8). Warning: cette solution convertit différents sauts de ligne (comme \r\n
) en \n
.
String result = new BufferedReader(new InputStreamReader(inputStream)).lines()
.parallel().collect(Collectors.joining("\n"));
Utilisation de InputStreamReader
et StringBuilder
(JDK)
final int bufferSize = 1024;
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
Reader in = new InputStreamReader(inputStream, "UTF-8");
for (; ; ) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
return out.toString();
Utilisation de StringWriter
et IOUtils.copy
(Apache Commons)
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, "UTF-8");
return writer.toString();
Utilisation de ByteArrayOutputStream
et 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");
Utilisation de BufferedReader
(JDK). Avertissement: Cette solution convertit différents sauts de ligne (tels que \n\r
) en propriété système line.separator
(par exemple, sous Windows, en "\ 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();
Utilisation de BufferedInputStream
et 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");
Utilisation de inputStream.read()
et StringBuilder
(JDK). Warning: cette solution a des problèmes avec Unicode, par exemple avec le texte russe (fonctionne correctement uniquement avec du texte non Unicode)
int ch;
StringBuilder sb = new StringBuilder();
while((ch = inputStream.read()) != -1)
sb.append((char)ch);
reset();
return sb.toString();
Attention:
Les solutions 4, 5 et 9 convertissent différents sauts de ligne en un.
Solution 11 ne peut pas fonctionner correctement avec le texte Unicode
Des tests de performance
Tests de performance pour les petits String
(longueur = 175), url dans github (mode = Temps moyen, système = Linux, le score 1 343 est le meilleur):
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
Tests de performance pour big String
(length = 50100), url in github (mode = Temps moyen, système = Linux, le score 200 715 est le meilleur):
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
Graphes (tests de performance en fonction de la longueur du flux d'entrée dans le système Windows 7)
Test de performance (temps moyen) en fonction de la longueur du flux d'entrée dans le système 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
Apache Commons permet:
String myString = IOUtils.toString(myInputStream, "UTF-8");
Bien sûr, vous pouvez choisir d’autres encodages de caractères en plus de UTF-8.
Voir aussi: ( documentation )
Compte tenu du fichier, il faut d’abord obtenir une instance Java.io.Reader
. Cela peut ensuite être lu et ajouté à une StringBuilder
(nous n'avons pas besoin de StringBuffer
si nous n'y avons pas accès, et StringBuilder
est plus rapide). L'astuce ici est que nous travaillons par blocs et que, par conséquent, nous n'avons pas besoin d'autres flux de mise en mémoire tampon. La taille de bloc est paramétrée pour l'optimisation des performances d'exécution.
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();
}
Utilisation:
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();
Si vous utilisez Google Collections/Guava, vous pouvez effectuer les opérations suivantes:
InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);
Notez que le second paramètre (c'est-à-dire Charsets.UTF_8) pour la variable InputStreamReader
n'est pas nécessaire, mais c'est généralement une bonne idée de spécifier le codage si vous le connaissez (ce que vous devriez!).
Ceci est ma solution pure Java et Android, et cela fonctionne bien ...
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;
}
Voici la solution la plus élégante en Java pur (sans bibliothèque) que j'ai trouvée après quelques expériences:
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();
}
Utilisation:
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();
}
Pour être complet, voici la solution Java 9:
public static String toString(InputStream input) throws IOException {
return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}
Le readAllBytes
est actuellement dans la base de code principale du JDK 9, il est donc susceptible de figurer dans la version. Vous pouvez l'essayer dès maintenant en utilisant le JDK 9 snapshot builds .
J'utiliserais quelques astuces 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.
}
}
Essentiellement les mêmes que d'autres réponses, à l'exception de plus succinctes.
J'ai fait un repère sur 14 réponses distinctes ici (désolé de ne pas fournir de crédits mais il y a trop de doublons).
Le résultat est très surprenant. Il s'avère que Apache IOUtils est la solution la plus lente et ByteArrayOutputStream
est la solution la plus rapide:
Alors d'abord, voici la meilleure méthode:
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);
}
}
Temps en millisecondes
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);
}
}
}
J'ai fait des tests de chronométrage, car le temps compte toujours.
J'ai essayé d'obtenir la réponse dans un String 3 différentes manières. (indiqué ci-dessous)
J'ai laissé de côté les blocs try/catch pour améliorer la lisibilité.
Pour donner un contexte, c'est le code précédent pour les 3 approches:
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();
Ainsi, après avoir exécuté 500 tests sur chaque approche avec les mêmes données de demande/réponse, voici les chiffres. Encore une fois, ce sont mes conclusions et vos conclusions peuvent ne pas être exactement les mêmes, mais j'ai écrit ceci pour donner une indication aux autres des différences d'efficacité de ces approches.
Rangs:
Approche # 1
Approche n ° 3 - 2,6% moins rapide que la n ° 1
Approche n ° 2 - 4,3% moins rapide que la n ° 1
Chacune de ces approches est une solution appropriée pour récupérer une réponse et en créer une chaîne.
Solution Java pure utilisant Stream s, fonctionne depuis 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()));
}
}
Comme mentionné par Christoffer Hammarström ci-dessous autre réponse il est plus sûr de spécifier explicitement le Charset . C'est à dire. Le constructeur InputStreamReader peut être modifié comme suit:
new InputStreamReader(is, Charset.forName("UTF-8"))
Voici la réponse plus ou moins sampath, nettoyée un peu et représentée en fonction:
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();
}
Si vous vous sentiez aventureux, vous pourriez mélanger Scala et Java et vous retrouver avec ceci:
scala.io.Source.fromInputStream(is).mkString("")
Le mélange de code et de bibliothèques Java et Scala présente des avantages.
Voir la description complète ici: Méthode idiomatique pour convertir un InputStream en String dans Scala
Si vous ne pouvez pas utiliser Commons IO (FileUtils/IOUtils/CopyUtils), voici un exemple d'utilisation de BufferedReader pour lire le fichier ligne par ligne:
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 si vous voulez une vitesse brute, je proposerais une variante de ce que Paul de Vrieze a suggéré (ce qui évite d'utiliser un StringWriter (qui utilise un StringBuffer en interne):
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);
}
}
Ceci est une réponse adaptée de org.Apache.commons.io.IOUtils
code source , pour ceux qui souhaitent avoir l’implémentation Apache mais ne veulent pas de la bibliothèque entière.
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();
}
Assurez-vous de fermer les flux à la fin si vous utilisez Stream Readers
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: Sur JDK 7+, vous pouvez utiliser la construction 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();
}
}
Voici la méthode complète pour convertir InputStream
en String
sans utiliser de bibliothèque tierce. Utilisez StringBuilder
pour un environnement à un seul thread, sinon utilisez 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();
}
Voici comment le faire en utilisant uniquement le JDK en utilisant des tampons de tableau d'octets. C’est en fait ainsi que fonctionnent toutes les méthodes commons-io IOUtils.copy()
. Vous pouvez remplacer byte[]
par char[]
si vous copiez à partir d'une Reader
au lieu d'une 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);
Un autre, pour tous les utilisateurs de 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);
}
Les méthodes utilitaires dans org.springframework.util.StreamUtils
sont similaires à celles de FileCopyUtils
, mais elles laissent le flux ouvert lorsque vous avez terminé.
Utilisez le Java.io.InputStream.transferTo (OutputStream) pris en charge en Java 9 et le ByteArrayOutputStream.toString (String) qui prend le nom du jeu de caractères:
public static String gobble(InputStream in, String charsetName) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo(bos);
return bos.toString(charsetName);
}
Les utilisateurs de Kotlin font simplement:
println(InputStreamReader(is).readText())
tandis que
readText()
est la méthode d’extension intégrée à la bibliothèque standard Kotlin.
Celui-ci est gentil parce que:
Qu'est-ce que le pour?
public static String convertStreamToString(InputStream is) {
if (is == null) return null;
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));
} catch (Throwable t) {}
return sb.toString();
}
Le moyen le plus simple dans JDK consiste à utiliser les extraits de code suivants.
String convertToString(InputStream in){
String resource = new Scanner(in).useDelimiter("\\Z").next();
return resource;
}
Voici ma solution basée sur Java 8, qui utilise la new Stream API pour collecter toutes les lignes d'une InputStream
:
public static String toString(InputStream inputStream) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream));
return reader.lines().collect(Collectors.joining(
System.getProperty("line.separator")));
}
inputStream.getText()
En termes de reduce
et concat
, il peut être exprimé en Java 8 par:
String fromFile = new BufferedReader(new
InputStreamReader(inputStream)).lines().reduce(String::concat).get();
J'ai écrit un cours qui ne fait que ça, alors je me suis dit que je le partagerais avec tout le monde. Parfois, vous ne voulez pas ajouter Apache Commons simplement pour une chose, et vous voulez quelque chose de plus bête que Scanner qui n'examine pas le contenu.
L'utilisation est comme suit
// Read from InputStream
String data = new ReaderSink(inputStream, Charset.forName("UTF-8")).drain();
// Read from File
data = new ReaderSink(file, Charset.forName("UTF-8")).drain();
// Drain input stream to console
new ReaderSink(inputStream, Charset.forName("UTF-8")).drainTo(System.out);
Voici le code pour ReaderSink:
import Java.io.*;
import Java.nio.charset.Charset;
/**
* A simple sink class that drains a {@link Reader} to a {@link String} or
* to a {@link Writer}.
*
* @author Ben Barkay
* @version 2/20/2014
*/
public class ReaderSink {
/**
* The default buffer size to use if no buffer size was specified.
*/
public static final int DEFAULT_BUFFER_SIZE = 1024;
/**
* The {@link Reader} that will be drained.
*/
private final Reader in;
/**
* Constructs a new {@code ReaderSink} for the specified file and charset.
* @param file The file to read from.
* @param charset The charset to use.
* @throws FileNotFoundException If the file was not found on the filesystem.
*/
public ReaderSink(File file, Charset charset) throws FileNotFoundException {
this(new FileInputStream(file), charset);
}
/**
* Constructs a new {@code ReaderSink} for the specified {@link InputStream}.
* @param in The {@link InputStream} to drain.
* @param charset The charset to use.
*/
public ReaderSink(InputStream in, Charset charset) {
this(new InputStreamReader(in, charset));
}
/**
* Constructs a new {@code ReaderSink} for the specified {@link Reader}.
* @param in The reader to drain.
*/
public ReaderSink(Reader in) {
this.in = in;
}
/**
* Drains the data from the underlying {@link Reader}, returning a {@link String} containing
* all of the read information. This method will use {@link #DEFAULT_BUFFER_SIZE} for
* its buffer size.
* @return A {@link String} containing all of the information that was read.
*/
public String drain() throws IOException {
return drain(DEFAULT_BUFFER_SIZE);
}
/**
* Drains the data from the underlying {@link Reader}, returning a {@link String} containing
* all of the read information.
* @param bufferSize The size of the buffer to use when reading.
* @return A {@link String} containing all of the information that was read.
*/
public String drain(int bufferSize) throws IOException {
StringWriter stringWriter = new StringWriter();
drainTo(stringWriter, bufferSize);
return stringWriter.toString();
}
/**
* Drains the data from the underlying {@link Reader}, writing it to the
* specified {@link Writer}. This method will use {@link #DEFAULT_BUFFER_SIZE} for
* its buffer size.
* @param out The {@link Writer} to write to.
*/
public void drainTo(Writer out) throws IOException {
drainTo(out, DEFAULT_BUFFER_SIZE);
}
/**
* Drains the data from the underlying {@link Reader}, writing it to the
* specified {@link Writer}.
* @param out The {@link Writer} to write to.
* @param bufferSize The size of the buffer to use when reader.
*/
public void drainTo(Writer out, int bufferSize) throws IOException {
char[] buffer = new char[bufferSize];
int read;
while ((read = in.read(buffer)) > -1) {
out.write(buffer, 0, read);
}
}
}
Basé sur la deuxième partie de la réponse acceptée par Apache Commons mais avec le petit espace comblé pour toujours fermer le flux:
String theString;
try {
theString = IOUtils.toString(inputStream, encoding);
} finally {
IOUtils.closeQuietly(inputStream);
}
Raghu K Nair Était le seul à utiliser un scanner . Le code que j'utilise est un peu différent:
String convertToString(InputStream in){
Scanner scanner = new Scanner(in)
scanner.useDelimiter("\\A");
boolean hasInput = scanner.hasNext();
if (hasInput) {
return scanner.next();
} else {
return null;
}
}
A propos des délimiteurs: Comment utiliser un délimiteur dans Java Scanner?
Le code ci-dessous a fonctionné pour moi.
URL url = MyClass.class.getResource("/" + configFileName);
BufferedInputStream bi = (BufferedInputStream) url.getContent();
byte[] buffer = new byte[bi.available() ];
int bytesRead = bi.read(buffer);
String out = new String(buffer);
Notez que, selon la documentation Java, la méthode available()
peut ne pas fonctionner avec InputStream
mais fonctionne toujours avec BufferedInputStream
. Si vous ne souhaitez pas utiliser la méthode available()
, nous pouvons toujours utiliser le code ci-dessous.
URL url = MyClass.class.getResource("/" + configFileName);
BufferedInputStream bi = (BufferedInputStream) url.getContent();
File f = new File(url.getPath());
byte[] buffer = new byte[ (int) f.length()];
int bytesRead = bi.read(buffer);
String out = new String(buffer);
Je ne suis pas sûr s'il y aura des problèmes d'encodage. Veuillez commenter, s'il y aura des problèmes avec le code.
Guava fournit une solution d'auto-fermeture efficace beaucoup plus courte dans le cas où le flux d'entrée provient d'une ressource de classpath (tâche qui semble être populaire):
byte[] bytes = Resources.toByteArray(classLoader.getResource(path));
ou
String text = Resources.toString(classLoader.getResource(path), StandardCharsets.UTF_8);
Il existe également le concept général de ByteSource et CharSource qui s’occupe en douceur de l’ouverture et de la fermeture du flux.
Ainsi, par exemple, au lieu d'ouvrir explicitement un petit fichier pour en lire le contenu:
String content = Files.asCharSource(new File("robots.txt"), StandardCharsets.UTF_8).read();
byte[] data = Files.asByteSource(new File("favicon.ico")).read();
ou juste
String content = Files.toString(new File("robots.txt"), StandardCharsets.UTF_8);
byte[] data = Files.toByteArray(new File("favicon.ico"));
public String read(InputStream in) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(in))) {
return buffer.lines().collect(Collectors.joining("\n"));
}
}
Avec Okio:
String result = Okio.buffer(Okio.source(inputStream)).readUtf8();
JDK 7/8 réponse qui ferme le flux et lève toujours une exception 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));
}
}
Vous pouvez utiliser Apache Commons.
Dans IOUtils, vous pouvez trouver la méthode toString avec trois implémentations utiles.
public static String toString(InputStream input) throws IOException {
return toString(input, Charset.defaultCharset());
}
public static String toString(InputStream input) throws IOException {
return toString(input, Charset.defaultCharset());
}
public static String toString(InputStream input, String encoding)
throws IOException {
return toString(input, Charsets.toCharset(encoding));
}
InputStream is = Context.openFileInput(someFileName); // whatever format you have
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[8192];
for (int bytesRead; (bytesRead = is.read(b)) != -1;) {
bos.write(b, 0, bytesRead);
}
String output = bos.toString(someEncoding);
InputStreamReader i = new InputStreamReader(s);
BufferedReader str = new BufferedReader(i);
String msg = str.readLine();
System.out.println(msg);
Voici s votre objet InputStream
qui sera converti en String
Essayez ces 4 déclarations ..
Selon le point rappelé par Fred, il n'est pas recommandé d'ajouter un opérateur String
avec +=
car chaque fois qu'un nouveau char
est ajouté à l'objet String
existant, créant à nouveau un nouvel objet String
et attribuant son adresse à st
tandis que l'ancien objet st
devient .
public String convertStreamToString(InputStream is)
{
int k;
StringBuffer sb=new StringBuffer();
while((k=fin.read()) != -1)
{
sb.append((char)k);
}
return sb.toString();
}
Non recommandé, mais c'est aussi un moyen
public String convertStreamToString(InputStream is) {
int k;
String st="";
while((k=is.read()) != -1)
{
st+=(char)k;
}
return st;
}
Eh bien, vous pouvez le programmer vous-même ... Ce n'est pas compliqué ...
String Inputstream2String (InputStream is) throws IOException
{
final int PKG_SIZE = 1024;
byte[] data = new byte [PKG_SIZE];
StringBuilder buffer = new StringBuilder(PKG_SIZE * 10);
int size;
size = is.read(data, 0, data.length);
while (size > 0)
{
String str = new String(data, 0, size);
buffer.append(str);
size = is.read(data, 0, data.length);
}
return buffer.toString();
}
Ce qui suit ne traite pas de la question initiale, mais plutôt de certaines des réponses.
Plusieurs réponses suggèrent des boucles de la forme
String line = null;
while((line = reader.readLine()) != null) {
// ...
}
ou
for(String line = reader.readLine(); line != null; line = reader.readLine()) {
// ...
}
La première forme pollue l'espace de noms de la portée englobante en déclarant une variable "read" dans la portée englobante qui ne sera utilisée pour rien en dehors de la boucle for. Le second formulaire duplique l'appel readline ().
Voici une manière bien plus propre d’écrire ce type de boucle en Java. Il s'avère que la première clause d'une boucle for ne nécessite pas de valeur d'initialiseur réelle. Cela permet de conserver l'étendue de la variable "line" dans le corps de la boucle for. Beaucoup plus élégant! Je n'ai vu personne utiliser ce formulaire où que ce soit (je l'ai découvert au hasard il y a un jour, il y a des années), mais je l'utilise tout le temps.
for (String line; (line = reader.readLine()) != null; ) {
//...
}
Vous pouvez utiliser Cactoos :
String text = new TextOf(inputStream).asString();
Le codage UTF-8 est celui par défaut. Si vous avez besoin d'un autre:
String text = new TextOf(inputStream, "UTF-16").asString();
Note: Ce n'est probablement pas une bonne idée. Cette méthode utilise la récursivité et frappe donc très rapidement une StackOverflowError
:
public String read (InputStream is) {
byte next = is.read();
return next == -1 ? "" : next + read(is); // Recursive part: reads next byte recursively
}
S'il vous plaît, n'enregistrez pas cela simplement parce que c'est un mauvais choix à utiliser; c'était surtout créatif :)
Utilisation:
String theString = IOUtils.toString(inputStream, encoding);
Cette solution à cette question n'est pas la plus simple, mais comme les flux et canaux NIO n'ont pas été mentionnés, voici une version qui utilise les canaux NIO et un ByteBuffer pour convertir un flux en chaîne.
public static String streamToStringChannel(InputStream in, String encoding, int bufSize) throws IOException {
ReadableByteChannel channel = Channels.newChannel(in);
ByteBuffer byteBuffer = ByteBuffer.allocate(bufSize);
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(encoding);
}
Voici un exemple d'utilisation:
try (InputStream in = new FileInputStream("/tmp/large_file.xml")) {
String x = streamToStringChannel(in, "UTF-8", 1);
System.out.println(x);
}
Les performances de cette méthode devraient être bonnes pour les gros fichiers.
InputStream inputStream = null;
BufferedReader bufferedReader = null;
try {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String stringBuilder = new StringBuilder();
String content;
while((content = bufferedReader.readLine()) != null){
stringBuilder.append(content);
}
System.out.println("content of file::" + stringBuilder.toString());
}
catch (IOException e) {
e.printStackTrace();
}finally{
if(bufferedReader != null){
try{
bufferedReader.close();
}catch(IoException ex){
ex.printStackTrace();
}
Méthode pour convertir inputStream en chaîne
public static String getStringFromInputStream(InputStream inputStream) {
BufferedReader bufferedReader = null;
StringBuilder stringBuilder = new StringBuilder();
String line;
try {
bufferedReader = new BufferedReader(new InputStreamReader(
inputStream));
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
} catch (IOException e) {
logger.error(e.getMessage());
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
logger.error(e.getMessage());
}
}
}
return stringBuilder.toString();
}
Ce fragment de code a été trouvé dans\sdk\samples\Android-19\connectivity\NetworkConnect\NetworkConnectSample\src\main\Java\com\exemple\Android\networkconnect\MainActivity.Java, sous licence Apache, Version 2.0 et écrit par Google .
/** Reads an InputStream and converts it to a String.
* @param stream InputStream containing HTML from targeted site.
* @param len Length of string that this method returns.
* @return String concatenated according to len parameter.
* @throws Java.io.IOException
* @throws Java.io.UnsupportedEncodingException
*/
private String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
String resultString = IOUtils.toString (userInputStream, "UTF-8");
J'ai créé ce code et cela fonctionne. Il n'y a pas de plug-in externe requis.
Il existe des chaînes de conversion en flux et de flux en chaînes ...
import Java.io.ByteArrayInputStream;
import Java.io.InputStream;
public class STRINGTOSTREAM {
public static void main(String[] args)
{
String text = "Hello Bhola..!\nMy Name Is Kishan ";
InputStream strm = new ByteArrayInputStream(text.getBytes()); // Convert String to Stream
String data = streamTostring(strm);
System.out.println(data);
}
static String streamTostring(InputStream stream)
{
String data = "";
try
{
StringBuilder stringbuld = new StringBuilder();
int i;
while ((i=stream.read())!=-1)
{
stringbuld.append((char)i);
}
data = stringbuld.toString();
}
catch(Exception e)
{
data = "No data Streamed.";
}
return data;
}
Je suggère le StringWriter class pour ce problème.
StringWriter wt= new StringWriter();
IOUtils.copy(inputStream, wt, encoding);
String st= wt.toString();
Vous pouvez également obtenir InputStream à partir d'un chemin de ressource spécifié:
public static InputStream getResourceAsStream(String path)
{
InputStream myiInputStream = ClassName.class.getResourceAsStream(path);
if (null == myiInputStream)
{
mylogger.info("Can't find path = ", path);
}
return myiInputStream;
}
Pour obtenir InputStream à partir d'un chemin spécifique:
public static URL getResource(String path)
{
URL myURL = ClassName.class.getResource(path);
if (null == myURL)
{
mylogger.info("Can't find resource path = ", path);
}
return myURL;
}