7

I need to get the size in bytes of an InputStream without creating a File instance. Is there any way to do it using Java NIO?

user1566669
  • 115
  • 1
  • 1
  • 5

4 Answers4

26

Of a general InputStream? You'd have to just keep reading and reading (e.g. into the same buffer, over and over) counting how many bytes you've read, until you come to the end of the stream.

Of course, you then won't be able to read the data itself... if you want to do that, you'll need to keep the data as you read it, e.g. by copying it to a ByteArrayOutputStream.

(If you're able to process the data at the same time as working out the length, just do that - as you read it using a loop, reading into the same buffer each time, just increment a counter to record how much you've read. You haven't really provided us any information about what you want to do with the stream.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    Or just copy it to the destination as you go, eliminate the counting, and the ByteArrayOutputStream, and the latency, and the space wasted by ready it all into memory. – user207421 Jul 31 '12 at 23:02
  • @EJP: That depends on what you're going to do with it afterwards. You may not be copying it to a destination at all. – Jon Skeet Aug 01 '12 at 05:45
  • So just read it and process it while you're doing so. I'm very suspicious of 'solutions' that start by reading the entire input, unless it is known that the input is very small, in which case you hardly need to know what size it is at all, do you? – user207421 Aug 01 '12 at 08:55
  • 1
    @EJP: Fundamentally, we just don't know what the OP is doing here. I edited my answer to indicate that. There are reasons for needing to know the size beforehand (e.g. if you're going to write it to a protocol which uses length-prefixing). – Jon Skeet Aug 01 '12 at 09:24
  • 1
    you can get the size of InputStream using getBytes(inputStream) of Utils.java check this following link http://www.java2s.com/Tutorial/Java/0180__File/GetbytesfromInputStream.htm – Gnanam R Mar 21 '13 at 12:16
6

It isn't knowable in principle (consider a peer that never stops writing), and you don't need it. Just read and write in a loop using a fixed size buffer. NIO doesn't offer any magical solution.

user207421
  • 305,947
  • 44
  • 307
  • 483
1

A couple of additional options:

Depending on the blocking nature of the input stream, you could call available() on the stream.

If the streams are smallish, you could write them into PushbackInputStreams, count the bytes and then rewind.

Nicholas
  • 15,916
  • 4
  • 42
  • 66
  • 1
    -1. available() does *not* return the size of a stream, and there is a specific warning in the Javadoc that says so. And *all* input streams are blocking. – user207421 Jul 31 '12 at 22:59
  • 6
    Have to contradict. Check the JavaDoc. http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#available%28%29. The return value of available() specifies that it is the number of bytes that can be read **without** blocking. Furthermore, "In some cases, a non-blocking read (or skip) may appear to be blocked when it is merely slow, for example when reading large files over slow networks". And in the case of FileInputStreams, it is frequently a reliable indicator of size. – Nicholas Aug 01 '12 at 15:24
  • 2
    That's exactly what I said. It is exactly the *opposite* of what you said. You said available() can be used to return the size of the input stream, which is the topic of this question. That's not the same thing as the number of bytes can that be read without blocking. Consider a socket. The part after 'furthermore' has no apparent relevance. There's another sentence you didn't quote that specifically warns against the usage in your last sentence, and there is nothing in the question about FileInputStream. – user207421 Aug 01 '12 at 22:12
  • @Nicholas "It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream" ;) https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/InputStream.html#available() – gouessej Jan 12 '23 at 09:08
-3

you can get the size of InputStream using getBytes(inputStream) of Utils.java check this following link

Get Bytes from Inputstream

Gnanam R
  • 397
  • 1
  • 3
  • 14
  • 1
    In other words just read the stream until end of stream, or rely on undocumented properties of ByteArrayInputStream. A very poor quality link, and it doesn't use NIO which was specified in the question. -1 – user207421 Jan 15 '14 at 09:28