java - 読み込み - string outputstream 変換
JavaでInputStreamをStringに変換する方法 (20)
Apache Commonsでは次のことが可能です。
String myString = IOUtils.toString(myInputStream, "UTF-8");
もちろん、UTF-8以外の文字エンコーディングを選択することもできます。
参照:( Docs )
java.io.InputStream
オブジェクトがある場合、そのオブジェクトをどのように処理してString
を生成する必要がありますか?
テキストデータを含むInputStream
があり、それをString
に変換したいとします。そのため、たとえばログファイルに書き込むことができます。
InputStream
をString
変換する最も簡単な方法は何ですか?
public String convertStreamToString(InputStream is) {
// ???
}
Google-Collections / Guavaを使用している場合は、次の操作を行うことができます:
InputStream stream = ...
String content = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
Closeables.closeQuietly(stream);
InputStreamReader
の2番目のパラメータ(Charsets.UTF_8)は必要ではないことに注意してください。しかし、それを知っていればエンコーディングを指定することはお勧めです
Guavaは、入力ストリームがクラスパスリソースから来た場合(これは一般的な作業のようです)には、効率の良い自動クローニングソリューションを提供します。
byte[] bytes = Resources.toByteArray(classLoader.getResource(path));
または
String text = Resources.toString(classLoader.getResource(path), StandardCharsets.UTF_8);
ByteSourceとCharSource一般的な概念もあり、ストリームの開始と終了の両方を静かに処理します。
例えば、小さなファイルを明示的に開いてその内容を読むのではなく、
String content = Files.asCharSource(new File("robots.txt"), StandardCharsets.UTF_8).read();
byte[] data = Files.asByteSource(new File("favicon.ico")).read();
あるいは単に
String content = Files.toString(new File("robots.txt"), StandardCharsets.UTF_8);
byte[] data = Files.toByteArray(new File("favicon.ico"));
Java 9のソリューションは完全なものです:
public static String toString(InputStream input) throws IOException {
return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}
readAllBytes
は現在JDK 9のメインコードベースにあるため、リリースに表示される可能性があります。 JDK 9のスナップショットビルドを使用して今すぐ試すことができます 。
JDKの最も簡単な方法は、次のコードスニペットを使用する方法です。
String convertToString(InputStream in){
String resource = new Scanner(in).useDelimiter("\\Z").next();
return resource;
}
Kotlinのユーザーは単純に次の操作を行います。
println(InputStreamReader(is).readText())
一方、
readText()
Kotlin標準ライブラリの組み込み拡張メソッドです。
いくつかの実験の後に私が思いついたもっともエレガントで純粋なJava(ライブラリなし)ソリューションがあります:
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();
}
ここには多かれ少なかれサンプンパスの答えがありますが、ちょっときれいにまとめられ、関数として表現されています:
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();
}
これはどう?
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();
これは私の純粋なJava&Androidソリューションで、うまくいきます...
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;
}
どのように:
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();
}
もう1つ、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);
}
inのユーティリティメソッドはinのorg.springframework.util.StreamUtils
ものと似ていますがFileCopyUtils
、完了したらストリームを開いたままにします。
ファイルを考慮に入れて、まずjava.io.Reader
インスタンスを取得する必要があります。 これを読み取ってStringBuilder
追加することができます(複数のスレッドでアクセスしない場合はStringBuffer
は不要で、 StringBuilder
は高速です)。 ここでのトリックは、ブロック単位で作業するため、他のバッファリングストリームを必要としないということです。 ブロックサイズは、実行時パフォーマンスの最適化のためにパラメータ化されています。
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();
}
他の回答を要約するこれを行う11の主な方法を見つけました(下記参照)。 そして私はいくつかのパフォーマンステストを書いた(下記の結果を参照):
InputStreamをStringに変換する方法:
IOUtils.toString
使用(Apache Utils)String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
CharStreams
使用(Guava)String result = CharStreams.toString(new InputStreamReader( inputStream, Charsets.UTF_8));
Scanner
(JDK)の使用Scanner s = new Scanner(inputStream).useDelimiter("\\A"); String result = s.hasNext() ? s.next() : "";
ストリームAPI (Java 8)の使用。 警告 :この解決策は、
\r\n
ような異なる改行を\n
変換します。String result = new BufferedReader(new InputStreamReader(inputStream)) .lines().collect(Collectors.joining("\n"));
パラレルストリームAPI (Java 8)の使用。 警告 :この解決策は、
\r\n
ような異なる改行を\n
変換します。String result = new BufferedReader(new InputStreamReader(inputStream)).lines() .parallel().collect(Collectors.joining("\n"));
InputStreamReader
および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();
StringWriter
とIOUtils.copy
使用(Apache Commons)StringWriter writer = new StringWriter(); IOUtils.copy(inputStream, writer, "UTF-8"); return writer.toString();
ByteArrayOutputStream
および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");
BufferedReader
(JDK)の使用。 警告:この解決策は、\n\r
などの異なる改行をline.separator
システムプロパティ(たとえば、Windowsでは "\ 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();
BufferedInputStream
および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");
inputStream.read()
とStringBuilder
(JDK)を使用しています。 警告 :このソリューションは、Unicodeに問題があります。たとえば、ロシア語のテキスト(Unicode以外のテキストでのみ正しく動作します)int ch; StringBuilder sb = new StringBuilder(); while((ch = inputStream.read()) != -1) sb.append((char)ch); reset(); return sb.toString();
警告 :
ソリューション4,5および9は、異なる改行を1に変換します。
ソリューション11はUnicodeテキストで正しく機能しません
パフォーマンステスト
小さなString
(長さ= 175)、 github URL(モード=平均時間、システム= Linux、スコア1,343が最適です)のパフォーマンステスト:
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
大きなString
(長さ= 50100)、 github URL(モード=平均時間、システム= Linux、スコア200,715が最適です)のパフォーマンステスト:
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
グラフ(Windows 7システムの入力ストリーム長に応じたパフォーマンステスト)
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
標準のJavaライブラリのみを使用する方法があります(ストリームは閉じられていないことに注意してください、YMMV)。
static String convertStreamToString(java.io.InputStream is) {
java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
return s.hasNext() ? s.next() : "";
}
私は"愚かなスキャナーのトリック"記事からこのトリックを学びました。 その理由は、 Scannerがストリーム内のトークンを反復処理するためです。この場合、「入力境界の始まり」(\ A)を使用してトークンを区切り、ストリームの内容全体に対してトークンを1つだけ与えます。
入力ストリームのエンコーディングについて具体的にする必要がある場合は、使用する文字セット(たとえば "UTF-8")を示す2番目の引数をScanner
コンストラクタにScanner
ことができます。
帽子の先端はJacob,も行きます。 Jacob,かつてこの記事に私を指摘しました。
EDITED: Patrickからの提案のおかげで、空の入力ストリームを扱うときに関数をより強固にしました。 もう1つの編集:不快な試み/キャッチ、パトリックの方法は不気味です。
私はいくつかの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.
}
}
基本的には、より簡潔なものを除いて他のいくつかの答えと同じです。
Java 9でサポートされているjava.io.InputStream.transferTo(OutputStream)と、文字セット名をとるByteArrayOutputStream.toString(String)を使用します。
public static String gobble(InputStream in, String charsetName) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo(bos);
return bos.toString(charsetName);
}
ここに私のJava 8ベースのソリューションは、新しいストリームAPIを使用してすべての行を収集する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
するための完全な方法を次に示しString
ます。使用するStringBuilder
使用それ以外の場合は、単一スレッド環境のために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();
}
バイト配列バッファを使用してJDKを使用する方法は次のとおりです。これは実際にコモンズIOUtils.copy()
メソッドがどのように動作するかです。。の代わりにからコピーbyte[]
しているchar[]
場合は、と置き換えることができます。Reader
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);