I am currently sending a request as shown below and was wanting to print out the response and exit. Is there a robust way of getting the whole response and then exiting, i.e., rather than breaking the loop after x lines or x seconds (which would have problematic cases)? Currently, the program never exits as the Scanner blocks waiting for more input. How else can I print out the response if not with some kind of loop/reader combination that might block?
public class PingHost {
public static void main(String[] args) throws Exception {
Socket s = new Socket("www.google.com", 80);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
out.writeBytes("GET / HTTP/1.1\n\n");
Scanner sc = new Scanner(s.getInputStream());
while (sc.hasNext())
System.out.println(sc.nextLine());
System.out.println("never gets to here");
s.close();
}
}
I am not 100 percent sure what you wanna do here.
But if you wanna just get the html of the answering page and move on afterwards, then give this code sample a try:
/**
* Example call:<br>
* sendHTTPRequestAndSysoutData("http://www.google.com");
* #param target
*/
public static void sendHTTPRequestAndSysoutData(String target){
try{
URL my_url = new URL(target);
BufferedReader br = new BufferedReader(new InputStreamReader(my_url.openStream()));
String strTemp = "";
while (null != (strTemp = br.readLine())){
System.out.println(strTemp);
}
}
catch(IOException e){
e.printStackTrace();
}
}
Related
I am trying to invoke a command prompt and logging in some credentials into it. For this I am taking following approach:
public static void main(String[] args) throws InterruptedException {
// init shell
ProcessBuilder builder = new ProcessBuilder("cmd");
Scanner scanner = null;
BufferedWriter writer = null;
try {
scanner = new Scanner (System.in);
System.out.print("Enter your MS ID : ");
String user = scanner.nextLine();
System.out.print("Enter your MS Password : ");
String pass = scanner.nextLine();
Process p = builder.start();
writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
writer.write("oc logout");
writer.newLine();
writer.flush();
writer.write("oc login <private-url>");
writer.newLine();
writer.flush();
writer.write(user);
writer.newLine();
writer.flush();
writer.write(pass);
writer.newLine();
writer.flush();
//Writing this will end the process after login is done
// writer.write("exit");
// writer.newLine();
// writer.flush();
Thread t = new Thread(new Runnable() {
public void run() {
try(BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
;
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
p.waitFor();
} catch (IOException e) {
System.out.println(e);
}
finally {
scanner.close();
}
}
But when I run the program, it just does not end. Eclipse and running by cmd always need to explicitly exit the program. Maybe I am missing something. Any help would be greatly appreciated. It just works for the desired thing but does not exit and I need to integrate in my program and not able to do so.
You don't close the writer!
Your loop in the runnable task asks the reader whether it has more input:
while ((line = br.readLine()) != null) { ... }
This is always the case unless the writer in the main thread is closed. So for a quick solution put a simple writer.close() after the last writing action.
The better solution is to use the try-with-resources statement, introduced with Java 7. You should open your readers, writers, scanners, etc. as following:
try (Scanner scanner = ...) { ... }
try {Reader reader = ...) { ... }
try {Writer writer = ...) { ... }
These statements will handle the closing automatically for you. And as a side effect, it will make your code much more readable.
Warning: Closing a Scanner which is connected with System.in also closes the standard input, so that after that point no input can be read anymore. If that is not appropriate in your part of the code, then do not close the scanner.
I am building a server in Java, and the input feed is giving me trouble - its current setup cannot read more than one line, and it cannot read anything without "\n" at the end. Here is the current input loop:
BufferedReader input = new BufferedReader(new InputStreamReader(serverConnection.getInputStream()));
if(input.ready()){
StringBuilder text = new StringBuilder();
String line;
while((line = input.readLine()) != null){
text.append(line);
System.out.println(line);
}
sentData = text.toString();
return true;
}
My current loop using a BufferedReader cannot read more than one line of incoming data, and if there is no newline character, a timeout exception is thrown (I programmed it to do that), and the data is not read at all. It is, of course, unacceptable to have a listener that can only see one line of data, and stalls when the sent data is not formatted properly.
So I am looking for a method that allows the program to read any number of lines, and for the program to stop reading when it has reached the end of the data stream (even without a new line).
Any help is appreciated.
You're throwing away every odd-numbered line. Remove the readLine() inside the loop.
You can read from the InputStream directly into the StringBuilder. readLine() of BufferedReader will wait for \r or \n character. This looks like stalling.
int ch;
StringBuilder text = new StringBuilder();
while((ch = serverConnection.getInputStream().read())!= -1) { // -1 will be read at EOS
text.append((char)ch);
}
sentData = text.toString();
return true;
Update
The following piece of code is to demonstrate the difference between usage of BufferedReader and InputStream to read bytes and what is available to the user during read operation. BufferedReader will always give you lines which are either terminated by line breaks or by EOS. Whereas InputStream will make the available bytes to the user.
In scenarios where it is NOT necessary to close the streams, and the bytes transferred has it's own way to mark start and end of packets/messages, you will be using InputStream to read bytes. If you try using BufferedReader for these applications, the last line of the message will be made available once the server receives the next packet/message, unless you send each line with a line-break.
public static void main(String[] args) throws Exception {
new Thread(new BufferedReaderServer()).start();
new Thread(new InputStreamServer()).start();
final String requestString = "Line#1\nLine#2";
System.out.println("\nSending to BufferedReaderServer");
Socket clientSocket1 = new Socket(InetAddress.getLocalHost()
.getHostAddress(), 8003);
OutputStream outputStream1 = clientSocket1.getOutputStream();
outputStream1.write(requestString.getBytes());
Thread.sleep(6000);
outputStream1.close();
clientSocket1.close();
Thread.sleep(1000);
System.out.println("\nSending to InputStreamServer");
Socket clientSocket2 = new Socket(InetAddress.getLocalHost()
.getHostAddress(), 8004);
OutputStream outputStream2 = clientSocket2.getOutputStream();
outputStream2.write(requestString.getBytes());
Thread.sleep(6000);
outputStream2.close();
clientSocket2.close();
}
static class BufferedReaderServer implements Runnable {
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8003);
Socket socket = serverSocket.accept();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
String s = null;
System.out.println("BufferedReaderServer read START");
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
System.out.println("BufferedReaderServer read END");
socket.getInputStream().close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
static class InputStreamServer implements Runnable {
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(8004);
Socket socket = serverSocket.accept();
System.out.println("InputStreamServer read START");
int ch;
while ((ch = socket.getInputStream().read()) != -1) {
System.out.print((char) ch);
}
System.out.println("\nInputStreamServer read END");
socket.getInputStream().close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
The issue what is being faced here could be due to non-closing of client socket. Depends on the user's application
I am trying to allow communication between one program (the program launcher, if you will) and the programs it launches via processbuilder. I have the output working fine, but the input seems to stop when it reaches the readline() method in helloworld (the created process).
Below is helloworld.java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class helloworld {
public static void main (String[] args) {
System.out.println ("println(\"Hello World!\")");
System.out.println ("getInput()");
Scanner in = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String input = "";
try {
// wait until we have data to complete a readLine()
while (!br.ready()) {
Thread.sleep(200);
}
System.out.println("println(\"Attempting to resolve input\")");
input = br.readLine();
^This is where program hangs^
if(input != null){
System.out.println("println(\"This should appear\")");
}
System.out.println("println(\"input recieved " + input + "\")");
} catch (InterruptedException | IOException e) {
System.out.println("ConsoleInputReadTask() cancelled");
}
System.out.println("println(\"You said: " + input + "\")");
//System.out.println("println(\"You said: " + in. + "!\")");
in.close();
System.exit(0);
}
}
This is where the output (println) from the other process is recieved:
public void run() {
try {
//cfile = files[indexval].getAbsolutePath();
String[] commands =
{
"java", //Calling a java program
"-cp" , //Denoting class path
cfile.substring(0,cfile.lastIndexOf(File.separator) ), //File path
program}; //Class name
ProcessBuilder probuilder = new ProcessBuilder( commands );
//start the process
Process process = probuilder.start();
//Read out dir output
//probuilder.inheritIO(); //Can inherit all IO calls
InputStream is = process.getInputStream();
OutputStream os = process.getOutputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
BufferedReader br = new BufferedReader(isr);
String line;
/*System.out.printf("Output of running %s is:\n",
Arrays.toString(commands));*/
while ((line = br.readLine()) != null) {
myController.runCommand(line, "Please enter something!", bw);
//System.out.println(line);
}
br.close();
os.close();
} catch (IOException e){
e.printStackTrace();
}
System.out.println("programclosed");
}
And here is the function that it calls:
public synchronized void runCommand(String line, Object... arguments) throws IOException {
String[] tokens;
if(line.contains("(")){
tokens = line.split("\\(",2);
switch(tokens[0]){
case "println": //Println - format println(String strng)
tokens[1] = tokens[1].substring(1, tokens[1].length() - 2);
System.out.println(tokens[1]);
break;
case "getInput": //Get input - format getInput(String command, String message, BufferedWriter br)
Scanner reader = new Scanner(System.in);
System.out.println(arguments.length);
System.out.println(((String)arguments[0]));
BufferedWriter in = ((BufferedWriter)arguments[1]);
in.write(reader.nextLine());
System.out.println("sending input");
in.flush();
reader.close();
break;
default:
System.out.println("Invalid command recieved!");
}
} else
System.out.println("Invalid command recieved!");
}
The output I recieve is:
Hello World!
2
Please enter something!
This is a test input
sending input
Attempting to resolve input
As you can see, I successfully exit the while(!br.ready()) loop, and I stop at br.readLine();
I am aware inheritIO() exist, but for this case I am using the BufferedOuput to send commands which are then parsed and sent to the switch statement, which in turn calls the corresponding function. This is because multiple processes could be launched from the process manager, think of the fun when multiple System.in calls arrive, with nothing to determine which process it is for! In addition, this allows for me to call any type of function, even those not related to println or input.
I believe the issue here is a result of the following:
BufferedReader.ready() returns true if there are any characters available to be read. It does not guarantee that there are any carriage returns among them. (docs)
BufferedReader.readLine() looks for a carriage return to complete a line. If one is not found, it blocks.
BufferedWriter.write() does not automatically write a terminating carriage return.
To test whether this is actually the problem, replace this line in runCommand():
in.write(reader.nextLine());
with:
in.write(reader.nextLine() + "\n");
Here is my problem, have a server and a client class which communicate via 2 threads (MsgWriter and MsgReader)
To read the input and write it in a stream i use a scanner.
It works but the Scanner need an input twice to continue.
For example:
I write a Message
Your Message: a text.
So i want to send the message right after i hit "enter"
but i have to press enter another time to send the text.
I'm sorry, i'm very bad in explaining. however here is the Code of the MsgWriter Thread
public class MsgWriter extends Thread {
private Socket s;
private Buffer buffer = new Buffer();
public MsgWriter(Socket s) {
this.s = s;
}
public void run() {
String message = "";
BufferedReader br = null;
boolean end = false;
while(!end){
try{
synchronized (buffer) {
while (!buffer.isEmpty()) {
buffer.wait();
}
//buffer.put(s);
OutputStream out = s.getOutputStream();
PrintStream writer = new PrintStream(out);
Scanner input = new Scanner(System.in);
input.useDelimiter("\n");
if (input.nextLine().equals("")){
System.out.println("Your message: ");
message = input.next();
br = new BufferedReader(new StringReader(message));
if (input.hasNext("x")) {
br = new BufferedReader(new StringReader("Good Bye"));
end = true;
}
message = br.readLine();
writer.println(message);
System.out.println("-------------------------------");
}
buffer.notifyAll();
}
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
}
}
And the Output
ServerIP: localhost/127.0.0.1
Port number: 56763
++ Connected to Server
Your message:
hi server
Received: hi client
Let me know if you need the Code of the MsgReader Thread as-well.
You have this line if (input.nextLine().equals("")) which looks for an empty string input and this is the reason your code waits for the second 'Enter' press. Any specific reason why you require this in the code?
I'm developing an application that has to receive multiple pieces of input from the user's terminal, while elegantly handling invalid input and prompting the user to re-enter it. My firs thought would be to have a while loop whose body will take the input and verify it's validity, setting a flag when it gets valid input. This flag will mark the stage the application is at and will determine what type of input is required next, and will also be used as the terminating condition of the loop.
While functional, this seems rather inelegant and I was wondering if there was a way I could simply write a function that is called whenever the return key is pressed to indicated that there is new input to be parsed. Something along the lines of
public class Interface {
public void receiveInput( final String input ){
// Parse 'input' for validity and forward it to the correct part of the program
}
}
Perhaps this could be achieved by extending some Java class and reimplementing one of it's functions that would normally handle such an event, but that's perhaps my C++ background talking.
I'm not allowed to use any external libraries, other than those requires for building and unit testing.
While reading from the console you can use BufferedReader
BufferedReader br = new BufferedReader( new InputStreamReader( System.in));
and by calling the readLine function, it will handle new line :
String readLine = br.readLine();
You can sure have a class in which there would be a function which reads the information and continue.
Here is the sample code for your reference
public class TestInput {
public String myReader(){
boolean isExit = true;
while (isExit){
System.out.print("$");
BufferedReader br = new BufferedReader( new InputStreamReader( System.in));
try {
String readLine = br.readLine();
if (readLine != null && readLine.trim().length() > 0){
if (readLine.equalsIgnoreCase("showlist")){
System.out.println("List 1");
System.out.println("List 2");
System.out.println("List 3");
} if (readLine.equalsIgnoreCase("shownewlist")){
System.out.println("New List 1");
System.out.println("New List 2");
} if (readLine.equalsIgnoreCase("exit")){
isExit = false;
}
} else {
System.out.println("Please enter proper instrictions");
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return "Finished";
}
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("Please Enter inputs for the questions asked");
TestInput ti = new TestInput();
String reader = ti.myReader();
System.out.println(reader);
}
Here is the output:
Please Enter inputs for the questions asked
$showlist
List 1
List 2
List 3
$shownewlist
New List 1
New List 2
$exit
Finished
Hope this helps.