io 이란 to - Java에서 InputStream을 String으로 읽거나 변환하는 방법은 무엇입니까?





15 Answers

다음은 표준 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)을 사용하여 토큰을 분리하므로 스트림의 전체 내용에 대해 하나의 토큰 만 제공합니다.

입력 스트림의 인코딩에 대해 구체적으로 설명 할 필요가있는 경우, 사용하는 캐릭터 세트 ( 「UTF-8」등)를 나타내는 2 번째의 인수를 Scanner 생성자에 제공 할 수 있습니다.

모자 팁은 제게 언급 한 기사를 한 번 지적한 Jacob, 에게 간다.

EDITED : Patrick 의 제안 덕분에 빈 입력 스트림을 처리 할 때 기능이 더욱 강력 해졌 습니다. 한 번 더 편집 : nixed try / catch, Patrick의 방법은 간결합니다.

util ioutils tostring

java.io.InputStream 객체가 있다면 그 객체를 어떻게 처리하고 String 생성해야합니까?

텍스트 데이터를 포함하는 InputStream 이 있다고 가정하고이를 String 으로 변환하려고합니다. 예를 들어이를 로그 파일에 쓸 수 있습니다.

InputStream 을 가져 와서 String 변환하는 가장 쉬운 방법은 무엇입니까?

public String convertStreamToString(InputStream is) { 
    // ???
}



Apache Commons는 다음을 허용합니다.

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

물론 UTF-8 외에도 다른 문자 인코딩을 선택할 수 있습니다.

참조 : ( Docs )




이것은 어떤가요?

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();



이것은 내 순수 자바 및 안드로이드 솔루션, 잘 작동합니다 ...

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



다음은 몇 가지 실험을 통해 나왔던 가장 우아하고 순수한 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();
}



나는 자바 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.
    }
}

기본적으로 더 간결한 것을 제외하고는 다른 답변과 같습니다.




Streams를 사용하는 순수 Java 솔루션은 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()));
    }
}

Christoffer Hammarström이 다른 답변 아래에서 언급했듯이, 명시 적으로 Charset 지정하는 것이 더 안전합니다. 즉, 다음과 같이 InputStreamReader 생성자를 변경할 수 있습니다.

new InputStreamReader(is, Charset.forName("UTF-8"))



좀 더 샘 퍼스의 답이 조금 깔끔 해지고 함수로 표현됩니다 :

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



Commons IO (FileUtils / IOUtils / CopyUtils)를 사용할 수 없다면 BufferedReader를 사용하여 한 줄씩 파일을 읽는 예제가 있습니다.

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

또는 원시 속도를 원한다면 Paul de Vrieze가 제안한 바리에이션을 제안 할 것입니다 (이는 StringBuffer를 내부적으로 사용하는 StringWriter 사용을 피합니다).

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



스트림 리더를 사용하는 경우 끝에 스트림을 닫아야합니다.

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

편집 : JDK 7 +에서는 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();
    }
}



다음은 바이트 배열 버퍼를 사용하는 JDK 만 사용하는 방법입니다. 이것은 실제로 commons-io IOUtils.copy()메소드가 모두 작동하는 방식입니다. . 대신에 복사 byte[]하는 char[]경우에를 사용하여 대체 할 수 있습니다 .ReaderInputStream

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



Kotlin 사용자는 단순히 다음을 수행합니다.

println(InputStreamReader(is).readText())

이므로

readText()

Kotlin 표준 라이브러리의 내장 확장 메소드입니다.




이 때문에 좋네요 :

  • 손 안전 Charset.
  • 읽기 버퍼 크기를 제어합니다.
  • 빌더의 길이를 프로비저닝 할 수 있으며 정확히 작성할 수 없습니다.
  • 라이브러리 의존성이 없습니다.
  • 자바 7 이상입니다.

그게 뭐야?

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



JDK에서 가장 쉬운 방법은 다음과 같은 코드 스 니펫입니다.

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



참고 : 이것은 아마도 좋은 생각이 아닙니다. 이 메서드는 재귀를 사용합니다.

public String read (InputStream is) {
    byte next = is.read();
    return next == -1 ? "" : next + read(is); // Recursive part: reads next byte recursively
}

사용하기에 나쁜 선택이기 때문에 이것을 downvote하지 마십시오; 이것은 주로 창조적이었다 :)




Related