Non-Blocking IO File in Java

I want to write to a named pipe (already created) without blocking it. My reader is another application that may go down. If the reader really goes down, I want the writer application to continue writing this named pipe. Something like this in Java

fopen(fPath, O_NONBLOCK) 

That way, when the reader appears, he can resume from where he failed.

+7
java named-pipes nonblocking nio
source share
4 answers

First I try to answer your questions. Then I will try to show you a piece of code that I created that solves your problem by blocking I / O.

Your questions

I want to write to a named pipe (already created) without blocking the reader

You do not need to block IO to solve your problem. I think this will not even help you solve your problem. Blocking I / O will also work well (perhaps even better than not blocking IO due to low concurrency). Plus blocks IO, easier to program. Your reader may / should remain blocked.

My reader is another application that may go down. If the reader really goes down, I want a neep writer application that writes a named pipe. So when the reader appears, he can resume from the place where he failed.

just put messages on the lock queue. Then write to the named pipe only when the reader reads from it (this happens automatically due to I / O blocking). No non-blocking IO file is needed when using a blocking queue. Data is transferred asynchronously from the lock queue when reading a reader, which sends your data from your writer to the reader.

Something like fopen (fPath, O_NONBLOCK) in Java

You do not need to block IO on the reader, and even if you used it. just use IO lock.

CODE SNIPPET

A created a small snippet that I think demonstrates your needs.

<strong> Components:

  • Writer.java : reads lines from the console as an example. When you run the program, enter the text and then enter that will send it to your named pipe. The author will resume recording if necessary.
  • Reader.java : reads lines written from your named pipe (Writer.java).
  • Named pipe I assume that you created a pipe named "pipe" in the same directory.

Writer.java

 import java.io.BufferedWriter; import java.io.Console; import java.io.FileWriter; import java.io.PrintWriter; import java.util.concurrent.BlockingDeque; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingDeque; import java.util.logging.Level; import java.util.logging.Logger; public class Writer { private final BlockingDeque<StringBuffer> queue; private final String filename; public static void main(String[] args) throws Exception { final Console console = System.console(); final Writer writer = new Writer("pipe"); writer.init(); while(true) { String readLine = console.readLine(); writer.write(new StringBuffer(readLine)); } } public Writer(final String filename){ this.queue = new LinkedBlockingDeque<StringBuffer>(); this.filename = filename; } public void write(StringBuffer buf) { queue.add(buf); } public void init() { ExecutorService single = Executors.newSingleThreadExecutor(); Runnable runnable = new Runnable() { public void run() { while(true) { PrintWriter w = null; try { String toString = queue.take().toString(); w = new PrintWriter(new BufferedWriter(new FileWriter(filename)), true); w.println(toString); } catch (Exception ex) { Logger.getLogger(Writer.class.getName()).log(Level.SEVERE, null, ex); } } } }; single.submit(runnable); } } 

Reader.java

 import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class Reader { private final BufferedReader br; public Reader(final String filename) throws FileNotFoundException { br = new BufferedReader(new FileReader(filename)); } public String readLine() throws IOException { return br.readLine(); } public void close() { try { br.close(); } catch (IOException ex) { Logger.getLogger(Reader.class.getName()).log(Level.SEVERE, null, ex); } } public static void main(String[] args) throws FileNotFoundException { Reader reader = new Reader("pipe"); while(true) { try { String readLine = reader.readLine(); System.out.println("readLine = " + readLine); } catch (IOException ex) { reader.close(); break; } } } } 
+8
source share

If you want the channels to remain active and send messages to the queue, you probably need a messaging system, not a raw channel. In Java, the standard API is called the "Java Messaging System" ( JMS ), and there are many standard implementations - the most common of which I've seen Apache ActiveMQ . If you want to use a cross-platform socket interface that performs buffering and recovery, I can offer 0MQ , which, although not pure Java, has bindings for many languages ​​and excellent performance.

+2
source share

If in Java there was something like non-blocking file I / O, which is not there, writing to a named pipe that was not read will return zero and write nothing. Therefore, non-blocking is not part of the solution.

There is also a problem that named pipes have a finite buffer size. They are not endless queues, regardless of whether there is a reading process or not. I agree with the proposal to learn JMS.

+1
source share

You can use NIO asynch write in UNIX FIFO, as in any other file:

  AsynchronousFileChannel channel = AsynchronousFileChannel.open(...); Future<Integer> writeFuture = channel.write(...); 

... or...

  channel.write(..., myCompletionHandler); 

However, it is not clear to me what you want when FIFO does not accept records. Do you want it to be buffered? If so, you need to provide it as part of the Java program. Do you want it time out? There is no simple timeout option when writing Java files.

These are not insurmountable problems. If you decide, you can probably do something. But I wonder if you will find life much if you just use a TCP socket or a JMS queue.

-one
source share

All Articles