when does FileInputStream.read() block? - java

The question is similar to the following two questions.
Java InputStream blocking read
Why is the FileInputStream read() not blocking?
But I still cannot fully understand it.
So far I think the read() method in following code will block due to the empty file 'test.txt'.
FileInputStream fis = new FileInputStream("c:/test.txt");
System.out.println(fis.read());
System.out.println("to the end");
Actually it will print -1, I want to know why.
The javadoc says This method blocks if no input is yet available.
What does 'no input is available' mean?
thanks.

The answer to your question can be found in the JavaDoc for .read():
This method blocks if no input is yet available.
and
Returns: the next byte of data, or -1 if the end of the file is reached.
So, an empty file will get you an immediate -1 (instead of read() blocking) as
there is input available, since the file exists
...but it is empty, so immediate EOF.
The ...No input is yet available... situation could occur eg. when one was to read from a named pipe instead of a plain file, and the other side of the pipe hasn't written anything yet.
Cheers,

FileInputStream can be used to read from things other than ordinary files. One obvious example is a named pipe: if you try to read from a pipe before the other side has written to it, the read operation will block.

This maybe interperted as follows: FileInputStream.read invokes a native method, the native method makes the read system call and blocks waiting for OS to read the bytes from file into a buffer and returns when ready. That is, FileInputStream.read uses synchronous I/O to reads data from a file as opposed to non-blocking, asynchronous I/O.

You can't interpret 'no input is available' as 'you are positioned at EOF and no more input will ever be available'. They are different conditions. The latter returns -1.
In general, all reads from files block until the data is available. The disk has to come around to the right point and the head has to seek to the right track. You also need to consider files that are on shared drives, or files that are named pipes, both of which involve network operations, which can also block.

Related

How to set a timeout when reading from a Java RandomAccessFile

I am writing to and reading from a Linux file in java, which in reality is a communication port to a hardware device. To do this I use RandomAccessFile (I'll explain why later) and it works well in most cases. But sometimes a byte is lost and then my routine blocks indefinitely since there is no timeout on the read method.
To give some more details on the file: it is a USB receipt printer that creates a file called /dev/usb/lp0 and though I can use a cups driver to print, I still need the low level communication through this file to query the status of the printer.
The reason I use RandomAccessFile is that I can have the same object for both reading and writing.
I tried to make a version with InputStream and OutputStream instead (since that would allow me to use the available() method to implement my timeout). But when I first open the InputStream and then the OutputStream I get an exception when opening the OutputStream since the file is occupied.
I tried writing with the OutputStream and then closing it before opening the InputStream to read, but then I lose some or all of the reply before it has opened the InputStream.
I tried switching to channels instead (Files.newByteChannel()). This also allows me to have just one object, and the documentation says it only reads the bytes available and returns the count (which also allows me to implement a timeout). But it blocks in the read method anyway when there is nothing to read, despite what the documentation says.
I also tried a number of ways to implement timeouts on the RandomAccessFile using threads.
The first approach was to start a separate thread at the same time as starting to read, and if the timeout elapsed in the thread I closed the file from the thread, hoping that this would unlock the read() operation with an exception, but it didn't (it stayed blocked).
I also tried to do the read in a separate thread and brutally kill it with the deprecated Thread.stop() once the time had elapsed. This worked one time, but it was not possible to reopen the file again after that.
The only solution I have made work is to have a separate thread that continuously calls read, and whenever it gets a byte it puts it in a LinkedBlockingQueue, which I can read from with a timeout. This approach works, but the drawback is that I can never close the file (again for the same reasons explained above, I can't unblock a blocked read). And my application requires that I sometimes close this connection to the hardware.
Anyone who can think of a way to read from a file with timeout that would work in my case (that allows me to have both a read and a write access open to the file at the same time)?
I am using Java8 by the way.

Is available method in InputStream a good way to iterate through a file?

From the document, the function of the "available" method is:
returns an estimate of the number of bytes that can be read (or
skipped over) from this input stream without blocking by the next
invocation of a method for this input stream.
So, how long does it take for this method to return a result. If I have a file with 10000 words, and I want to go through each word by checking like this:
while (steam.available() > 0) {
steam.read(); // suppose that this read a word
}
So after each reading the first word, is the method going to go through the next 9999 words? And, after the second word, do it check the next 9998 words?
From the document, it say that the method "estimate the number of bytes", then how does it do that?
As it states, the purpose is to tell you how many bytes you can read without the read call blocking. This is mostly useful for network connections, where data is filling the buffer and you might want to process as much of that data without the read call blocking, waiting for more data.
It's not commonly used and doesn't tell you anything about how much is GOING to be available over all. For example, iv seen it used to test the length of a message, which is of course wrong, because only a part of the message may have been received at that point.
You are best to just read the whole stream until EOF is reached. available() will only be of use if you want to process as much data as you can without blocking. it says "estimate" because more data could be coming in all the time and you may have been able to read more bytes than available() returned at the exact moment you called it.
In practice, you need all the data from a stream, or you stop when you reach a certain value. But this is a separate issue to how quickly it streams in from where ever it's coming from. Wether it blocks or not - you will neither know nor care. :)

what are the concern regarding simultaneous read and write to a file?

consider the following scenario:
Process 1 (Writer) continuously appends a line to a file ( sharedFile.txt )
Process 2 (Reader) continuously reads a line from sharedFile.txt
my questions are:
In java is it possible that :
Reader process somehow crashes Writer process (i.e. breaks the process of Writer)?
Reader some how knows when to stop reading the file purely based on the file stats (Reader doesn't know if others are writing to the file)?
to demonsterate
Process one (Writer):
...
while(!done){
String nextLine;//process the line
writeLine(nextLine);
...
}
...
Process Two (Reader):
...
while(hasNextLine()){
String nextLine= readLine();
...
}
...
NOTE:
Writer Process has priority. so nothing must interfere with it.
Since you are talking about processes, not threads, the answer depends on how the underlying OS manages open file handles:
On every OS I'm familiar with, Reader will never crash a writer process, as Reader's file handle only allows reading. On Linux, system calls a Reader can potentially invoke on the underlying OS are open(2) with O_RDONLY flag, lseek(2) and read(2) -- are known not to interfere with the syscalls that the Writer is invoking, such as write(2).
Reader most likely won't know when to stop reading on most OS. More precisely, on some read attempt it will receive zero as the number of read bytes and will treat this as an EOF (end of file). At this very moment, there can be Writer preparing to append some data to a file, but Reader have no way of knowing it.
If you need a way for two processes to communicate via file, you can do it using some extra files that pass meta-information between Readers and Writers, such as whether there are Writer currently running. Introducing some structure into a file can be useful too (for example, every Writer appends a byte to a file indicating that the write process is happening).
For very fast non-blocking I/O you may want consider memory mapped files via Java's MappedByteBuffer.
The code will not crash. However, the reader will terminate when the end is reached, even if the writer may still be writing. You will have to synchronize somehow!
Concern:
Your reader thread can read a stale value even when you think another writer thread has updated the variable value
Even if you write to a file if synchronization is not there you will see a different value while reading
Java File IO and plain files were not designed for simultaneous writes and reads. Either your reader will overtake your writer, or your reader will never finish.
JB Nizet provided the answer in his comment. You use a BlockingQueue to hold the writer data while you're reading it. Either the queue will empty, or the reader will never finish. You have the means through the BlockingQueue methods to detect either situation.

When Does Scanner.nextLine() block?

I'm using a Scanner for my socket connection in a Client/Server program.
I want Scanner.next() to block so the Server thread can wait for something to read.
However, it sometimes gives me:
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1585)
at cscie55.hw4.Server.serviceClient(Server.java:146)
at cscie55.hw4.Server.main(Server.java:106)
The java documentation says that next() "sometimes" blocks, and it doesn't say whether nextLine() blocks.
Some code online wraps it in an if that tests for null, but I read that it never returns null. What should I do to get blocking IO working properly in my socket?
Specifically,
When does Scanner.nextLine() block rather than throw NoSuchElementException?
The Scanner class will block whenever the InputStream used to construct it would block. It will usually not block when reading from a file because the contents of it are readily available (i.e., inputStream.available() > 0), they are on your machine after all. However, if you construct a Scanner using an InputStream that may require waiting for data to arrive (e.g., reading text from a remote client, waiting for a page to load so you can read its source, etc.) then Scanner#nextLine() will block because it needs to wait for enough information to build the next line to arrive.
It blocks if it's reading from a network and there is no data or no newline present in the input and it hasn't reached EOS. You must be reading from a file.

How do i check if inputstream contains no data?

I am using the javax.comm package to perform read and write operations on the SerialPort.
I have created an object of type InputStream as InputStream in;
My question is ....
Irrespective of data availibility on the SerialPort, in.available() always returns a zero due to which I am not able to decide whether bytes are available or not.
If i use the in.read() directly, it seems to block the execution forever..
Please help...
Awaiting your reply..
You can also mail me on my email address..
In anticipation of your reply....
Utsav
This is typical behavior of block I/O. The read() is going to block till some bytes are available, EOF or error. You should create a new thread and just wait for more data.
Don't use available() call because it may create a fast loop and drive up your CPU usage. If you really want do this in a single thread, looking into NIO.

Categories

Resources