Write a stream into a file with NIO and the Channel system - java

I have an inputStream and i want to write it to a file.
I saw NIO and the FileChannel which has the method "transferTo" ou "transferFrom" and i know how to create the WriteableChannel, but i don't know to transform my inputStream to a ReadableChannel.
Thanks.

Have a look at the Channels.newChannel(java.io.InputStream) method.
newChannel
public static ReadableByteChannel newChannel(InputStream in)
Constructs a channel that reads bytes from the given stream.
The resulting channel will not be buffered; it will simply redirect
its I/O operations to the given stream. Closing the channel will in
turn cause the stream to be closed.
Parameters:in - The stream from which bytes are to be read
Returns:A new readable byte channel

Related

How to close a Java's socket's outputstream while keeping the inputstream open to get a result?

I'm sending a message to a server, which passes correctly.
But, when trying to read the result, I get an exception that the Socket is closed.
Any idea how to close the socket's outputstream while keeping the socket and socket's inputstream open to get the result?
Client code:
Socket socket = new Socket("localhost", 9090);
String message = "Some message";
new OutputStreamWriter(socket.getOutputStream(), Charsets.UTF_8)
.append(message)
.close();
// The following line throws the exception when socket.getInputStream() is called:
String fromServer = CharStreams.toString(new InputStreamReader(socket.getInputStream(), Charsets.UTF_8));
Exception:
java.net.SocketException: Socket is closed
at java.net.Socket.getInputStream(Socket.java:903)
at alik.server.test.Client.pingServer(Client.java:24)
From the javadoc of Socket.getOutputStream():
Closing the returned OutputStream will close the associated socket.
In other words, don't close the output stream until you are done with the input stream. Closing the input stream will also close the socket (and as a result, also the output stream).
You could use Socket.shutdownOutput() to prevent further writing to the socket, but I don't really see the point of using that, and it could result in the peer closing its socket prematurely, as Stephen C explains in the comments:
The peer should only see the closed stream if it reads. What happens
next will depend on how it responds to seeing the closed stream.
You can't close an OutputStream without closing the socket(See two links below). Is there a specific reason why you need to do this?
You would need to finish read/writing before you close the socket and it's input/output streams.
Returns an output stream for this socket.
If this socket has an associated channel then the resulting output stream delegates all of its operations to the channel. If the channel is in non-blocking mode then the output stream's write operations will throw an IllegalBlockingModeException.
Closing the returned OutputStream will close the associated socket.
Behavior of Java sockets when closing output stream
https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#getOutputStream()
As mentioned by Joseph, I don't think you should close the OutputStream before opening the InputStream.
According to Oracle Docs (https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html), the correct order is:
Open a socket.
Open an input stream and output stream to the socket.
Read from and write to the stream according to the server's protocol.
Close the streams.
Close the socket.
To only close the output stream, use
socket.shutdownOutput()
See docs
You can't. Closing a socket input or output stream closes the other stream and the socket.
However the real problem here is that the peer is trying to read until end of stream before it sends anything back. This is an applicaton protocol issue. You could overcome it by shutting down the sending socket for output after sending everything that is to be sent, as mentioned by #MarkRotteveel, but this restricts you to one request/response per connection.
It would be better to review your application protocol to discover how the peer can know where the end of a request is, and only read that far before replying. For example, possibly you should be sending lines.

How to read a DataInputStream twice or more than twice?

I have a Socket connection to an application that I hosted elsewhere. Once I connected I made a OutputStream and DataInputStream.
Once the connection has been made, I use the OutputStream to send out a handshake packet to the application. Once this handshake has been approved, it returns a packet through the DataInputStream (1).
This packet is processed and is returned to the application with the OutputStream.
If this returned data is valid, I get another packet from the DataInputStream (2). However, I have not been able to read this packet through the DataInputStream.
I have tried to use DataInputStream.markSupported() and DataInputStream.mark() but this gave me nothing (except for an empty Exception message).
Is it possible to read the input stream for a second time? And if so, can someone please point me out what I'm doing wrong here?
EDIT: Here is my solution:
// First define the Output and Input streams.
OutputStream output = socket.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
// Send the first packet to the application.
output.write("test"); // (not actual data that I sent)
// Make an empty byte array and fill it with the first response from the application.
byte[] incoming = new byte[200];
bis.read(incoming); //First packet receive
//Send a second packet to the application.
output.write("test2"); // (not actual data that I sent)
// Mark the Input stream to the length of the first response and reset the stream.
bis.mark(incoming.length);
bis.reset();
// Create a second empty byte array and fill it with the second response from the application.
byte[] incoming2 = new byte[200];
bis.read(incoming2);
I'm not sure if this is the most correct way to do this, but this way it worked for me.
I would use ByteArrayInput stream or something that you can reset. That would involve reading the data into another type of input stream and then creating one.
InputStream has a markSupported() method that you could check on the original and the byte array one to find one that the mark will work with:
https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#markSupported()
https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html
The problem here is not re-reading the input. I don't see anything in the question that requires you to read the input twice. The problem is the BufferedInputStream, which will read everything that is available to be read, including the second message, if it has already arrived.
The solution is not to use a buffered stream until you have completed the handshake. Just issue a read on the socket input stream for exactly the length of the first message, do the handshake, and then proceed to construct and read the buffered stream.

Java Spring-integration TCP flush control

I am using spring-integration and the ServerSocketFactory is set to have decent receive and write buffers, as well as TCPNoDelay is set to false. This is verified set correctly on the socket with a debugger.
When writing to the outputstream in the spring-integration serializer, I see each write call being sent seperately with a TCP PSH (push) flag - i.e. a flush.
Why does this flush occur? How can I avoid this?
You would need to customize the serializer - they generally flush after all parts have been written (e.g. length header + payload; payload + CRLF; STX + payload + ETX; etc, etc).
Simply subclass the serializer of your choice and override the serialize() method to remove the flush(). Inject it into the connection factory.
EDIT:
Oh, I see - Nagle's algorithm only applies to subsequent writes (notice the payload and ETX are in a single packet). We need to wrap the stream in a buffered output stream. Please open a JIRA issue.
In the meantime, you can work around it with something like this...
/**
* Writes the byte[] to the stream, prefixed by an ASCII STX character and
* terminated with an ASCII ETX character.
*/
#Override
public void serialize(byte[] bytes, OutputStream outputStream) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
bos.write(STX);
bos.write(bytes);
bos.write(ETX);
bos.flush();
}

Is it necessary to close input/output streams created from a socket's IO streams when the socket closes?

private val in = new BufferedReader(new InputStreamReader(con.getInputStream()))
private val out = new PrintWriter(con.getOutputStream(), true)
try {
while (true) {
if (in.readLine() == null)
throw new IOException("connection reset by peer")
}
} catch {
case e: Exception =>
} finally {
// Is this necessary?
in.close()
out.close()
// Close socket
con.shutdownInput()
con.shutdownOutput()
con.close()
}
If any IO streams or reader/writers is created from socket's input or output stream, is it necessary to close them before or after socket is closed?
If any IO streams or reader/writers is created from socket's input or output stream, is it necessary to close them before or after socket is closed?
You should close the outermost OutputStream or Writer you have created from the socket output stream. That will flush the stream and close the socket and its input stream. Closing any other aspect of the socket, such as its direct output stream, its input stream or anything wrapped around it, or the socket itself, accomplishes most but not all of that: specifically, closing the input stream before the output stream as you have in your example prevents the output stream being flushed and so can lose data.
Calling shutdownInput() or shutdownOutput() immediately before a close is always redundant.
From the Socket Javadoc:
Closing this socket will also close the socket's InputStream and OutputStream.
Of course, any readers/writers your code explicitly opened should also be explicitly closed, but as far as network resources are concerned, they will be released regardless.
As far as the ordering of actions is concerned, the standard rules apply: last to open -> first to close. So definitely close all your readers/writers before closing the underlying socket connection.
It is not necessary in this case, but it does no harm.
However, if you haven't set the "autoFlush" flag in the PrintWriter constructor, then if you didn't close or flush the Writer before closing the Socket, some data might not be sent. (And if you closed in the wrong order, you could get an exception!)
For readers / input streams this is not a concern. You've already decided to ignore any buffered input.
There is no concern with leaking resources (file descriptors). If the Socket is closed, all I/O resources are released. You don't need to call shutdownInput or shutdownOutput either. Closing the Socket will do that.

Recording audio not to file on Android

I want android.media.MediaRecorder. to record audio not into file, but into same variable, for example char[ ] or byte[ ] or some other datta buffer structure. I want to send it to the remote server via Wi-Fi, can android.media.MediaRecorder provide this functionality?
What you can do here is utilize the ParcelFileDescriptor class.
//make a pipe containing a read and a write parcelfd
ParcelFileDescriptor[] fdPair = ParcelFileDescriptor.createPipe();
//get a handle to your read and write fd objects.
ParcelFileDescriptor readFD = fdPair[0];
ParcelFileDescriptor writeFD = fdPair[1];
//next set your mediaRecorder instance to output to the write side of this pipe.
mediaRecorder.setOutputFile(writeFD.getFileDescriptor());
//next create an input stream to read from the read side of the pipe.
FileInputStream reader = new FileInputStream(readFD.getFileDescriptor());
//now to fill up a buffer with data, we just do a simple read
byte[] buffer = new byte[4096];//or w/e buffer size you want
//fill up your buffer with data from the stream
reader.read(buffer);// may want to do this in a separate thread
and now you have a buffer full of audio data
alternatively, you may want to write data directly to a socket from the recorder. this can also be achieved with the ParcelFileDescriptor class.
//create a socket connection to another device
Socket socket = new Socket("123.123.123.123",65535);//or w/e socket address you are using
//wrap the socket with a parcel so you can get at its underlying File descriptor
ParcelFileDescriptor socketWrapper = ParcelFileDescriptor.fromSocket(socket);
//set your mediaRecorder instance to write to this file descriptor
mediaRecorder.setOutputFile(socketWrapper.getFileDescriptor());
now any time your media recorder has data to write it will automatically write it over the socket

Categories