[java] एक स्ट्रिंग में एक इनपुट स्प्रैड को पढ़ें / कन्वर्ट करें


Answers

यहां केवल मानक जावा लाइब्रेरी का उपयोग करने का एक तरीका है (ध्यान दें कि स्ट्रीम बंद नहीं है, वाईएमएमवी)।

static String convertStreamToString(java.io.InputStream is) {
    java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
    return s.hasNext() ? s.next() : "";
}

मैंने इस चाल को "बेवकूफ स्कैनर चाल" लेख से सीखा। कारण यह काम करता है क्योंकि Scanner स्ट्रीम में टोकन पर पुनरावृत्ति करता है, और इस मामले में हम "इनपुट सीमा की शुरुआत" (\ ए) का उपयोग करके टोकन को अलग करते हैं, इस प्रकार हम स्ट्रीम की पूरी सामग्री के लिए केवल एक टोकन देते हैं।

नोट, यदि आपको इनपुट स्ट्रीम के एन्कोडिंग के बारे में विशिष्ट होना आवश्यक है, तो आप Scanner कन्स्ट्रक्टर को दूसरा तर्क प्रदान कर सकते हैं जो इंगित करता है कि किस वर्ण का उपयोग करना है (उदाहरण के लिए "यूटीएफ -8")।

हैट टिप Jacob, को भी जाता है Jacob, जिसने मुझे एक बार लेख में बताया था।

संपादित: Patrick से एक सुझाव के लिए धन्यवाद, एक खाली इनपुट स्ट्रीम को संभालने के दौरान समारोह को और अधिक मजबूत बना दिया। एक और संपादन: मिश्रित कोशिश / पकड़, पैट्रिक का रास्ता अधिक लापरवाही है।

Question

यदि आपके पास java.io.InputStream ऑब्जेक्ट है, तो आप उस ऑब्जेक्ट को कैसे संसाधित कर सकते हैं और String उत्पादन कैसे कर सकते हैं?

मान लीजिए मेरे पास एक InputStream है जिसमें टेक्स्ट डेटा है, और मैं इसे String कनवर्ट करना चाहता हूं। उदाहरण के लिए, इसलिए मैं स्ट्रीम की सामग्री को लॉग फ़ाइल में लिख सकता हूं।

InputStream लेने और इसे String बदलने का सबसे आसान तरीका क्या है?

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



Another one, for all the Spring users:

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

The utility methods in org.springframework.util.StreamUtils are similar to the ones in FileCopyUtils , but they leave the stream open when done.




यह मेरा शुद्ध जावा और एंड्रॉइड समाधान है, अच्छी तरह से काम करता है ...

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



Guava provides much shorter efficient autoclosing solution in case when input stream comes from classpath resource (which seems to be popular task):

byte[] bytes = Resources.toByteArray(classLoader.getResource(path));

या

String text = Resources.toString(classLoader.getResource(path), StandardCharsets.UTF_8);

There is also general concept of ByteSource and CharSource that gently take care of both opening and closing the stream.

So, for example, instead of explicitly opening a small file to read its contents:

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



कैसा रहेगा:

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



अपाचे कॉमन्स अनुमति देता है:

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

बेशक, आप यूटीएफ -8 के अलावा अन्य चरित्र एन्कोडिंग चुन सकते हैं।

यह भी देखें: ( Docs )




मैं कुछ जावा 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.
    }
}

अनिवार्य रूप से कुछ अन्य उत्तरों के समान ही संक्षेप में छोड़कर।







Raghu K Nair Was the only one using a scanner. The code I use is a little different:

String convertToString(InputStream in){
    Scanner scanner = new Scanner(in)
    scanner.useDelimiter("\\A");

    boolean hasInput = scanner.hasNext();
    if (hasInput) {
        return scanner.next();
    } else {
        return null;
    }

}

About Delimiters: How do I use a delimiter in Java Scanner?




Here is the complete method for converting InputStream into String without using any third party library. Use StringBuilder for single threaded environment otherwise use 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();
}



This is an answer adapted from org.apache.commons.io.IOUtils source code , for those who want to have the apache implementation but do not want the whole library.

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



I did a benchmark upon 14 distinct answers here(Sorry for not providing credits but there are too many duplicates)

The result is very surprising. It turns out that Apache IOUtils is the slowest and ByteArrayOutputStream is the fastest solutions:

So first here is the best method:

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

Benchmark results, of 20MB random bytes in 20 cycles

Time in milliseconds

  • ByteArrayOutputStreamTest: 194
  • NioStream: 198
  • Java9ISTransferTo: 201
  • Java9ISReadAllBytes: 205
  • BufferedInputStreamVsByteArrayOutputStream: 314
  • ApacheStringWriter2: 574
  • GuavaCharStreams: 589
  • ScannerReaderNoNextTest: 614
  • ScannerReader: 633
  • ApacheStringWriter: 1544
  • StreamApi: Error
  • ParallelStreamApi: Error
  • BufferReaderTest: Error
  • InputStreamAndStringBuilder: Error

Benchmark source code

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

}



Stream एस का उपयोग कर शुद्ध जावा समाधान, जावा 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()));
    }
}

जैसा कि अन्य उत्तर के नीचे क्रिस्टोफर हैमरस्ट्रॉम द्वारा वर्णित है, स्पष्ट रूप से Charset निर्दिष्ट करना सुरक्षित है। Ie इनपुटस्ट्रीम रीडर कन्स्ट्रक्टर निम्नानुसार परिवर्तन हो सकता है:

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



यदि आप साहसी महसूस कर रहे थे, तो आप स्कैला और जावा मिश्रण कर सकते हैं और इसके साथ समाप्त हो सकते हैं:

scala.io.Source.fromInputStream(is).mkString("")

जावा और स्कैला कोड और पुस्तकालयों को मिलाकर इसका लाभ होता है।

यहां पूरा विवरण देखें: स्केल में एक स्ट्रिंग में एक इनपुटस्ट्रीम को परिवर्तित करने के लिए बेवकूफ तरीका




इस बारे में कैसा है?

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



Related