java كيفية قراءة / تحويل InputStream إلى سلسلة في جاوة؟





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) مما يمنحنا رمزًا واحدًا فقط لمحتويات البث بالكامل.

ملاحظة ، إذا كنت بحاجة إلى أن تكون محددًا حول ترميز دفق الإدخال ، فيمكنك تقديم الوسيطة الثانية إلى منشئ Scanner الذي يشير إلى مجموعة الأحرف المستخدمة (على سبيل المثال "UTF-8").

يذهب تلميح قبعة أيضا إلى Jacob, الذي أشار لي مرة واحدة على المادة المذكورة.

EDITED: بفضل اقتراح من Patrick ، جعل الوظيفة أكثر قوة عند التعامل مع تدفق مدخلات فارغ. تحرير واحد آخر: محاولة / صيد نيكس ، طريقة باتريك أكثر مقتضبة.

java string io stream inputstream

إذا كان لديك كائن 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.
    }
}

أساسا نفس بعض الإجابات الأخرى باستثناء أكثر مقتضبة.




حل جافا الصافي باستخدام Stream s ، يعمل منذ 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 أن تحدد 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();
}



إذا لم تتمكن من استخدام نظام التشغيل العام لـ Office (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 (والذي يتجنب استخدام StringWriter (الذي يستخدم StringBuffer داخليًا):

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 فقط باستخدام المخازن المؤقتة لصفيف البايت. هذا هو في الواقع كيف IOUtils.copy()تعمل جميع أساليب commons-io . يمكنك استبدال 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);



مستخدمو 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;
}



توفر الجوافة حلًا أوتوماتيكيًا أقصر بكثير في حالة ما إذا كان مصدر المدخلات يأتي من مورد الفئات (الذي يبدو مهمة شائعة):

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

هناك أيضًا مفهوم عام عن ByteSource و CharSource الذي CharSource برفق بفتح وغلق البث.

لذلك ، على سبيل المثال ، بدلاً من فتح ملف صغير بشكل واضح لقراءة محتوياته:

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

أو فقط

 String content = Files.toString(new File("robots.txt"), StandardCharsets.UTF_8); byte[] data = Files.toByteArray(new File("favicon.ico")); 



Related