views:

2590

answers:

3

My current situation is I have to read in a file and place it in an InputStream, and then also place the contents of the InputStreaminto a byte array which requires that i know the size of the InputStream. Any ideas?

As requested, i will show the input stream that i am creating from an uploaded file

 InputStream uploadedStream = null;
  FileItemFactory factory = new DiskFileItemFactory();
  ServletFileUpload upload = new ServletFileUpload(factory);
  java.util.List items = upload.parseRequest(request);   
  java.util.Iterator iter = items.iterator();

  while (iter.hasNext()) {
      FileItem item = (FileItem) iter.next();
      if (!item.isFormField()) {
       uploadedStream = item.getInputStream();
          //CHANGE uploadedStreambyte = item.get()
      }
  }

request is a HttpServletRequest object, and FileItemFactory adn ServletFileUpload are from Apache Commons FileUpload

+5  A: 

You can't determine the amount of data in a stream without reading it; you can, however, ask for the size of a file:

http://java.sun.com/javase/6/docs/api/java/io/File.html#length()

If that isn't possible, you can write the bytes you read from the input stream to a ByteArrayOutputStream which will grow as required.

Andrew Duffy
In my scenario the inputstream contains an uploaded file from a HTML form, i can't get the file size since i'm not loading the file off the hard drive.
ChronoXIII
If your input stream has mark() support, you could mark at the beginning and just read through it entirely - then reset() and start processing it.
kd304
the file is an image (potentially large) so reading through the stream twice would cause performance issues wouldn't it?
ChronoXIII
Try it. If it’s very slow you have performance issues. Otherwise, you don’t. It’s that simple.
Bombe
@ChronoXIII: True. This is why I asked for a small code sample so we could see your scenario. If your image is already in memory (thanks to fileupload or something) then it opens more options.
kd304
+10  A: 

I would read into a ByteArrayOutputStream and then call toByteArray() to get the resultant byte array. You don't need to define the size in advance (although it's possibly an optimisation if you know it. In many cases you won't)

Brian Agnew
I seem to have found that inputstream have a toString() method and then i can just call a getBytes() to create a byte array off of the string. I'm wondering if there are any performance issues from doing this?
ChronoXIII
You need to be careful with bytes/character conversions. Is this originally a byte stream ? If it contains characters, how are they encoded etc. If you're getting these via a network connection, I would suspect that's your main performance bottleneck and I wouldn't worry about conversion overhead
Brian Agnew
I currently read the inputstream with the image into a database as a binarystream, this seems to work well as i can read the file back out afterwords and its still an image
ChronoXIII
That sounds good!
Brian Agnew
Thanks for your help everyone, unless there is any reason not to go with a convert stream to string using .toString() and then to byte array using .getBytes(), i will continue with this solution.
ChronoXIII
I wopuld have thought it's easier to read in a loop from your inputstream to the byte array output stream, and then get the byte array, thus avoiding char encodings. But if you're happy that toString() works...
Brian Agnew
Yes, there is. String.getBytes() will have conversion issues.
kd304
Alright so if String.getBytes really has a type conversion issue will the following changes to my code work (shown in initial post with //CHANGE)
ChronoXIII
Yes. You get the full raw byte array, no conversion, no issues.
kd304
Alright thank you
ChronoXIII
+2  A: 

I just wanted to add, Apache Commons IO has stream support utilities to perform the copy. (Btw, what do you mean by placing the file into an inputstream? Can you show us your code?)

Edit:

Okay, what do you want to do with the contents of the item? There is an item.get() which returns the entire thing in a byte array.

Edit2

item.getSize() will return the uploaded file size.

kd304
I currently save the file to a blob field in the database and i send it as a binarystream (input as a inputstream), now i require the inputstream in a byte array since i need to make a signature of data and the function only takes byte arrays.
ChronoXIII
item.get() nets you the byte array, as I mentioned. And don't worry about performance an size unless you are working with several MB images.
kd304
That could be the case since the image is uploaded by a user, and i can't seem to find a way to auto trim images on the server side. :(
ChronoXIII
What do you mean by auto trim images? get() will give you the entire uploaded file(image) as byte[]. Then you go ahead and use it on any OutputStream.write(), wrap it to ByteArrayInputStream again, etc.
kd304
I changed the solution to this post since its answer was more fine tuned for my current setup
ChronoXIII