BufferedInputStream is throwing out-of-memory errors in Android - java

I'm trying to use a BufferedInputStream to load an external DICOM file, but it eventually runs out of memory. When I used an InputStream, this never came up (I did this when I was loading the file through the assets folder).
I created my own producer-consumer threads to buffer the file, so I don't actually need the BufferedInputStream, but I DO need to use mark() and reset() which is not available in FileInputStream.
How should I go around this? Is there another kind of InputStream that I can use with a File which has the mark()/reset() functions? Can I empty the buffer somehow before the BufferedInputStream throws the error? Or should I find a way around using mark() instead?
Thanks for your input.

For mark and reset to work with buffered input the file points between the mark and reset need to remain in memory.
Workarounds depend on what you're actually trying to do; if you just need to start reading from a known location, perhaps a RandomAccessFile.

Related

Reading an image in Java with threads

I have a question regarding reading images in Java. I am trying to read an image using threads and i was curious whether by doing this:
myInputFile = new FileInputStream(myFile);
I already read the whole data or not. I already read it in 4 chunks using threads and i am curious whether I just read it twice, once with threads and once with FileInputStream, or what does FileInputStream exactly do. Thanks in advance!
The FileInputStream is not reading your file yet, just by calling it like: myInputFile = new FileInputStream(myFile);.
It basically only gives you a handle to the underlying file and prepares to read from it by opening a connection to that file. Also it runs some basic checks including whether the file exists and if its a proper file and not a directory.
Following is stated in the JavaDocs which you can find here:
Creates a FileInputStream by opening a connection to an actual file,
the file named by the File object file in the file system. A new
FileDescriptor object is created to represent this file connection.
First, if there is a security manager, its checkRead method is called
with the path represented by the file argument as its argument.
If the named file does not exist, is a directory rather than a regular
file, or for some other reason cannot be opened for reading then a
FileNotFoundException is thrown.
Only by calling the FileInputStream.read methods it starts to read and return the contents of the file.
Thereby the FileInputStream.read() method will only read one single byte of the file and the FileInputStream.read(byte[] b) method will read as many bytes as the size of the byte array b.
Edit:
Because reading a file byte by byte is pretty slow and the usage of the plain FileInputStream.read(byte[] b) method can be a bit cumbersome it's a good practice to use the BufferedInputStream to process files in Java.
It'll read by default the next 8192 bytes of a file and buffer it in-memory for faster access. So the BufferedInputStream.read method will still only return a single byte per call, but in the BufferedInputStream it'll mainly be served from an internal buffer. As long the requested bytes are in this buffer, they'll be served from it. The underlying file will be accessed again only when really needed (-> the requested byte is not in the buffer anymore). This drastically reduces the number of read accesses to the hardware (which in comparison is the slowest operation in this process) and therefore boosts the reading performance a lot.
The initialization looks like this:
InputStream i = new BufferedInputStream(new FileInputStream(myFile));
The handling of it is exactly same as with the 'plain' FileInputStream, since they share the same InputStream interface.

How to evaluate size of file in Java before creating it?

In my Java programm I need to create files and write in it something that i can get by Inputstream's read() method. How can I evaluate the size of file before creating it?
Normally, you don't need to know how big the file will be, but if you really do:
The only way you could do that would be to fully read the content from the InputStream into memory first, and then see how much you have.
You have several options for how to read it all into memory, one of which might be to write it to a ByteArrayOutputStream. (And then, of course, write that out to the file when you're ready.)
But again, the great thing about streams is that you don't have to read things all into memory; if you can avoid needing to know the size in advance, that would be best.
Also note that the space the file will occupy on disk won't be exactly the same as the file size; most file systems work in chunks (4k, 8k, 16k, 32k) and so a file that's (say) 12k on a file system using 8k chunks will actually occupy 16k of space.
It's depend of the encoding used, but you can write it in memorystream and get the length.

How to create an InputStream of files that have a certain extension in Java?

I have a lot of files in a directory but I only want to read the ones with a certain extension (say .txt). I want these files added to the same BufferedInputStream so that I can read them in one go. When I call read() at the end of a file, the next one should begin.
It really feels like there should be an obvious answer to this but I had no luck finding it.
You might want to take a look at SequenceInputStream:
A SequenceInputStream represents the logical concatenation of other
input streams. It starts out with an ordered collection of input
streams and reads from the first one until end of file is reached,
whereupon it reads from the second one, and so on, until end of file
is reached on the last of the contained input streams.
To me the "obvious answer" is:
Just iterate through all the files in the directory using a proper filter. For each file create a FileInputStream, read it and close it.
I don't think there is an obvious answer to this question.
Probably you need to create a Wrapper InputStream with a list of files you want to read from. Internally you will open/close streams as needed, namely when a file is completely read.
It is not obvious but should not be difficult. This way you can work 'only' with one InputStream for all files.

Custom Buffered Input Stream for on-the-fly reading/pull

I need to pass an InputStream to an object which reads data which I previously stored into a File. I'm assessing a more efficient approach than storing eveything into a File and then passing the FileInputStream. I'd like to do it on the fly.
May someone appoint me the correct approach to do that?
The idea would be passing a Custom InputStream which innerly calls every line I was going to store in the file. I guess I need buffering. I discard storing everything in a String and then build an InputStream on it, as we are in the same situation, waiting to output all the lines before rereading them again.
There already is a stream for this. It's the PipedInputStream. You'll need to have one thread write to the PipedOutputStream, and pass the PipedInputStream to the object that will be reading in another thread.

Separating multiple images from stdin in Java

I want to write a program in Java with support for unix pipeline. The problem is that my input files are images and I need in some way to separate them from one another.
I thought that there is no problem because I can read InputStream using ImageIO.read() without reseting position. But it isn't that simple. ImageIO.read() closes the stream every time an image is read. So I can't read more than one file from stdin. Do you have some solution for this?
The API for read() mentions, "This method does not close the provided InputStream after the read operation has completed; it is the responsibility of the caller to close the stream, if desired." You might also check the result for null and verify that a suitable ImageReader is available.

Categories