I wanted to create something like a remote control for the command line in Windows.
For this I am using a scanner, but...
The problem is, when I read the whole line with nextLine() from the stream, the prompt will be missing (becouse is is printed, but not in a line) - and when I read the next word with next(), the line break is missing and you will lose the overview. However, some information is even missing.
package com;
import java.io.IOException;
import java.util.Scanner;
public class StdinCmd extends Thread {
public void run() {
try {
execute();
} catch (IOException e) {
e.printStackTrace();
}
}
public void execute() throws IOException {
Scanner reader = new Scanner(MainClient.getProcess().getInputStream()); // <- getting the stream
StdoutSocket stdoutSocket = new StdoutSocket();
while (true) {
while (reader.hasNext()) {
stdoutSocket.executeNext(reader.next()); // <- send it to the socket (the controller). This is what will be displayed at the end.
}
}
}
}
I attached a screenshot of how it should look like, and how it looks at the end:
http://www.mediafire.com/?jma31ezg8ansfal
I hope you can help me and I gave you enough information!
Don't use Scanner or BufferedReader, but instead read directly from the InputStream...
InputStream is = null;
try {
is = MainClient.getProcess().getInputStream();
int in = -1;
while ((in = is.read()) != -1) {
System.out.print(((char)in));
}
} catch (IOException exp) {
exp.printStackTrace();
} finally {
try {
is.close();
} catch (Exception exp) {
}
}
Personally I really don't like scanner so much. If you want to read input line's from a user and send it through a socket.. Who not then just use a BufferedReader with System.in?
Read a line and send it through the socket.
BufferedReader br = new BUfferedReader(new InputStreamReader(System.in));
String line = null;
while((line = br.readLine()) != null){
OutSocket.send(line); // or how you send it..
}
~Foorack
Related
I'm using BufferedReader to read data from System.in (a text file redirected context: < file.txt) then write it to the console. The problem is my program shows all lines except the last one and still works without doing any thing. If I manually end it it will write the final line.
This is my code:
public void updateText() throws IOException {
try {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String inputLine;
while ((inputLine = bufferedReader.readLine()) != null) {
System.out.println(inputLine);
}
inputStreamReader.close();
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Here an alternative way of waiting on available data (Ref.: Java 11 - method BufferedReader.ready()):
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
class TestClass {
public static void main(String[] args) {
try (InputStreamReader inputStreamReader = new InputStreamReader(System.in);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
String line;
// wait until data available
while (!bufferedReader.ready()){
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Example output:
Hello world
Hello world
Hello world
Hello world
If this only occurs in Eclipse, your issue is most likely a duplicate and bug 513713.
You don't need to read standard input line by line when you could simply transfer the data in one step, replacing the body of updateText():
System.in.transferTo(System.out);
I am trying to implement a simple java server and client - where client sends "hey" and server sends "hello" back. The problem I am having is even though the server sees hey but client never receives hello.
Here is the server code
try {
InputStream input = clientSocket.getInputStream();
System.out.println("client's request"+ IOUtils.toString(input));
OutputStream output = clientSocket.getOutputStream();
PrintWriter pw = new PrintWriter(output);
pw.write("hello");
pw.flush();
/*BufferedOutputStream bf = new BufferedOutputStream(output);
bf.write("hello".getBytes());*/
/*output.write(("hello").getBytes());*/
long time = System.currentTimeMillis();
System.out.println("Request processed: " + time);
}
catch (IOException e)
{
// report exception somewhere.
e.printStackTrace();
}
Client program
Socket s = new Socket("localhost",9000);
OutputStream out = s.getOutputStream();
out.write("hey".getBytes());
/*PrintWriter pw = new PrintWriter(out);
pw.write("hey");
pw.flush(); */
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while((line =br.readLine())!= null)
{
System.out.println(line);
}
s.close();
I have different variations of reading and writing the input/output but with no luck. Suggestions please.
Thanks
This won't work. IOUtils.toString(input) will read from the input until end of stream, which won't occur until the peer closes the connection, which won't occur at all because he is blocked in readLine() trying to read the response to the request that you are blocked forever reading.
Use BufferedReader.readLine(), but without the loop you have in the client.
This
void writeLine(BufferedWriter writer, String text) throws IOException {
writer.write(text); // the actual characters we want to send
writer.newLine(); // something that signals the end of the message.
writer.flush(); // and we must enforce that these bytes are sent and not buffered locally.
}
can be read by
String readLine(BufferedReader reader) throws IOException {
// reads characters until it finds either a newline or end of stream
// returns data or null when the stream has already ended
return reader.readLine();
}
When you send messages over sockets you must make sure that you have some kind of "protocol" to delimit your messages. For example by sending a newline after each message. That way both sides know where messages in a continuous stream of data ends.
Besides sending the right kind message, you also have to make sure to actually send it. BufferedWriter for example has a data-buffer and will not send data until the buffer is full enough. This will in most cases mean that messages will remain in the buffer instead of being sent over the wire. To do that call flush() once you have written everything you need.
I have different variations of reading and writing the input/output but with no luck.
In your case you don't send a newline but wait for it via readLine. The client should have actually received the "hello" part but it's not going to return from readLine without newline/end of stream (which should happen if you stop the server at this point). The same should apply to the message you send to your server but I guess you do kill the client at this point and therefore see the message.
Here is also the code I made while playing around with this
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.CountDownLatch;
class Hello {
static int port = 12345;
private static void writeLine(BufferedWriter writer, String line) throws IOException {
System.out.println(">> " + line);
writer.write(line); // the actual characters that we want to send
writer.newLine(); // something that signals the end of the message.
writer.flush(); // and we must enforce that these bytes are sent and not buffered locally.
}
private static String readLine(BufferedReader reader) throws IOException {
// reads characters until it finds either a newline or the end of the stream
// returns data or null when the stream has already ended
return reader.readLine();
}
static void handle(Socket cs, boolean controlling) {
try (Socket socket = cs) {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
if (controlling) {
writeLine(writer, "hey");
}
loop: while (!Thread.currentThread().isInterrupted()) {
String readLine = readLine(reader);
System.out.println("<< " + readLine);
if (readLine == null)
break;
switch (readLine) {
case "hey":
writeLine(writer, "ho");
break;
case "ho":
writeLine(writer, "bye");
break;
case "bye":
break loop;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
static void server(CountDownLatch latch) {
try (ServerSocket ss = new ServerSocket(port)) {
System.out.println("Listening.");
latch.countDown();
while (!Thread.currentThread().isInterrupted()) {
Socket clientSocket = ss.accept();
// spawn a new thread per client
new Thread(() -> handle(clientSocket, false)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
static void client() {
System.out.println("Connecting.");
try (Socket socket = new Socket("localhost", port)) {
System.out.println("Connected.");
handle(socket, true);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
new Thread(() -> server(latch)).start();
latch.await();
new Thread(() -> client()).start();
}
}
In the method getFileName() created the object BufferedReader and assigned reference to the object to the variable - reader. Then stream closed in the finally.
Then invoked the method readStringsFromConsole(). There creates the same object. But thrown IOException. Why did it happen ?
ps: sorry for my English :)
stacktrace:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
at java.io.BufferedInputStream.read(BufferedInputStream.java:336)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at com.test.home04.Solution.readStringsFromConsole(Solution.java:55)
code:
import java.io.*;
import java.util.*;
public class Solution
{
public static void main(String[] args)
{
String fileName = getFileName();
ArrayList<String> listStrings = readStringsFromConsole();
writeToFileFromList(fileName, listStrings);
}
public static void writeToFileFromList (String fileName, ArrayList<String> listInputString)
{
PrintWriter writer = null;
try {
writer = new PrintWriter(fileName, "UTF-8");
for (String stringItem : listInputString)
writer.write(stringItem);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static ArrayList<String> readStringsFromConsole() {
BufferedReader reader = null;
ArrayList<String> listInputString = new ArrayList<String>();
String line = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
line = reader.readLine();
if ("exit".equals(line))
break;
listInputString.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return listInputString;
}
}
public static String getFileName()
{
BufferedReader reader = null;
String fileName = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (fileName == null) {
fileName = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
}
}
If you create a reader from System.in and close it, it also closes System.in, which can't be opened again even if you create another reader.
In short - don't close readers which are created from System.in.
Also as Andreas pointed out in the comment, the general guideline should be that System.in should only ever be wrapped once in the lifetime of the command-line program (whether by Scanner, BufferedReader, or something else), and it should never be closed. The wrapping should likely occur at the beginning of main(), and the wrapper object should either be passed around or stored in a field (static or instance).
Why did it happen ?
It happened because you closed System.in in your getFilename method.
Why not open the stream after the close?
Basically, because you can't, or if you are asking about the behavior of the JVM ... >>it<< can't.
When close() is called, the close gets sent to the operating system which closes and releases the underlying file descriptor. Once closed, the OS does not have enough information to reopen the previous file. And if the file descriptor was for an (unnamed) pipe or socket stream, then the connection cannot be remade because:
the application or service at the other end will typically have gone away,
in the case of a TCP/IP socket, the protocol does not allow reconnection.
In short: don't close a stream if you need to read or write more from / to it later, and avoid closing System.{in,out,err} entirely.
Now if your application had a filename or a host / port, it could open a new FileReader or connect a new socket. But in the case of the System.* streams, that information is not available to the application (or the JVM).
But in your particular case, I suspect that your intention is that getFileName returns the filenames supplied one at a time; i.e. each call returns the next filename. If that is the case, you will have to implement it differently:
It shouldn't close the stream or the reader.
It shouldn't open the reader (probably).
It should return the first (or next) line that it reads rather than reading all lines and returning the last one, as it currently does.
You are closing the stream from System.in. Closed stream needs to be opened before reusing it. Don't close them if you create them from System.in.
Try this,
import java.io.*;
import java.util.*;
public class Solution
{
public static void main(String[] args)
{
String fileName = getFileName();
ArrayList<String> listStrings = readStringsFromConsole();
writeToFileFromList(fileName, listStrings);
}
public static void writeToFileFromList (String fileName, ArrayList<String> listInputString)
{
PrintWriter writer = null;
try {
writer = new PrintWriter(fileName, "UTF-8");
for (String stringItem : listInputString)
writer.write(stringItem);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static ArrayList<String> readStringsFromConsole() {
BufferedReader reader = null;
ArrayList<String> listInputString = new ArrayList<String>();
String line = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
line = reader.readLine();
if ("exit".equals(line)) {
break;
}
listInputString.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
//do not close the stream
//reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return listInputString;
}
}
public static String getFileName()
{
BufferedReader reader = null;
String fileName = null;
try {
reader = new BufferedReader(new InputStreamReader(System.in));
while (fileName == null) {
System.out.println("Enter a file name: ");
fileName = reader.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null)
//do not close the stream
//reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return fileName;
}
}
}
Here is the situation:
I have a java application which executes another java application example.exe (example.exe has some System.out.println("...");)
I want to get the output Stream from example.exe so i tried with something like that:
(looks pretty standard)
final Process process = Runtime.getRuntime().exec("example.exe");
new Thread() {
public void run() {
try {
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
try {
while((line = inputReader.readLine()) != null) {
inputText = inputText + line;
}
System.out.println(inputText);
} finally {
inputReader.close();
}
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
I would like to get the output messages of example.exe but it doesn't work and i don"t understand why, i get one message but not the one from example.exe, probably from java or something else.
i want to read anything written in the terminal the Java class read it and store it in variable to use it in another method
can any one help me?
public class Termainl {
public static void main (String args[] ) throws IOException{
String[] cmdArray = {"gnome-terminal","java -classpath /home/r/byz/ Orchestrator"};
try {
Runtime.getRuntime().exec(cmdArray);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I don't think you can easily get the output of the console like this but you can get the output of the process you launch. Why not directly launch the process and get its output.
You could try something like this:
try {
Runtime.getRuntime().exec( "java -classpath /home/r/byz/ Orchestrator" );
String line;
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null) {
//<-- Parse data here.
}
input.close();
} catch (Exception err) {
//......
}