Quote:

When I was working on the project, I encountered a problem, that is, the pictures read from the network had to be uploaded to oss, and the pictures had to be clipped and compressed. InputStream of the picture was used for both uploading and clipping. Because inputStream could not be read repeatedly, clipping was successful, while uploading failed. Today we will provide two methods to solve the problem that inputStream cannot be read repeatedly.

Problem analysis:

InputStream has a pos pointer inside it. The pointer moves continuously when it is read, and when it reaches the end, it cannot be read again. Let’s write a simple example:

    String text = "Test inputStream content";
    InputStream inputStream = new ByteArrayInputStream(text.getBytes());
    byte[] readArray = new byte[inputStream.available()];
    int readCount1 = inputStream.read(readArray);
    System.out.println("Read" + readCount1 + "Byte");

    byte[] readArray2 = new byte[inputStream.available()];
    int readCount2 = inputStream.read(readArray2);
    System.out.println("Read" + readCount2 + "Byte");
    /** * the result is * 23 bytes read * -1 bytes read */

Copy the code

As you can see from the execution, inputStream is designed to be read only once. Note: inputStream.available() can be used to determine the size of a local file, but it is best not to use inputStream.available() if the data is on the network, because the transfer is not continuous, the data size will be inaccurate.

Problem solving:

So how should we solve it in the actual project? You can’t just use inputSteam once. Let’s look at the workaround: Method 1: Cache bytes using A ByteArrayOutputStream and fetch them from the cached ByteArrayOutputStream each read. We naturally want to cache inputStream (not necessarily ByteArrayOutputStream, but other ways to cache inputStream). There are many ways to cache inputStream.

       String text = "Test inputStream content";
       InputStream rawInputStream = new ByteArrayInputStream(text.getBytes());
       ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
       byte[] buffer = new byte[1024];
       int len;
       while ((len = rawInputStream.read(buffer)) > -1) {
           outputStream.write(buffer, 0, len);
       }
       outputStream.flush();
       InputStream in1 = new ByteArrayInputStream(outputStream.toByteArray());
       InputStream in2 = new ByteArrayInputStream(outputStream.toByteArray());
       int readCount1 = in1.read(buffer);
       int readCount2 = in2.read(buffer);
       System.out.println("Read" + readCount1 + "Byte");
       System.out.println("Read" + readCount2 + "Byte");
       /** * the result is that 23 bytes have been readCopy the code

Output is read from inputStream, and output is read from inputStream again and again. Output can be read from inputStream again and again, and input can only be read once.

InputStream has two pointer manipulation methods: mark and reset. Before we use inputSteam, we mark the position of the inputStream pointer, read it, reset it, and then we can use it again and again. Let’s look at the code:

      String text = "Test inputStream content";
      InputStream rawInputStream = new ByteArrayInputStream(text.getBytes());
      byte[] readArray = new byte[1024];
      rawInputStream.mark(0);
      int readCount1 = rawInputStream.read(readArray);
      rawInputStream.reset();
      int readCount2 = rawInputStream.read(readArray);
      System.out.println("Read" + readCount1 + "Byte");
      System.out.println("Read" + readCount2 + "Byte");
Copy the code

Conclusion:

1. InputStream can only read once, that is, only call read() or any other read() method with an argument once, and the next call will read -1. 2. You can reuse inputStream using caching or mark/reset methods. It is important to note that caching is not a good idea if inputStream has a lot of content, because it takes up a lot of memory before it is used up. Then the CPU burst first); 3. Don’t forget to turn off inputStream/outputSteam when you’re done.