I want a simple server socket to accept a client and read some texts and disconnect the client from itself. As a client I'm using a telnet for now, because in the future I will create a custom program.
ServerSocket ss = new ServerSocket(SERVER_SOCKET_PORT);
Socket s = ss.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
while (true) {
line = reader.readLine();
if (line == null || line == "" || line == "q") {
log("-- breaking the loop");
break;
}
printf("**%s%n", line);
}
reader.close();
s.close();
ss.close();
The problem I'm having is the while loop never breaks.
First, that isn't how you compare String(s) for equality. Second, I would prefer String.isEmpty() to testing for equality with "". Finally, you can use a try-with-resources to close everything. Something like,
try (ServerSocket ss = new ServerSocket(SERVER_SOCKET_PORT);
Socket s = ss.accept();
BufferedReader reader = new BufferedReader(
new InputStreamReader(s.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.isEmpty() || line.equalsIgnoreCase("q")) {
System.out.println("-- breaking the loop");
break;
}
System.out.printf("**%s%n", line);
}
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
line = reader.readLine();
if (line == null || line == "" || line == "q") {
The problem I'm having is the while loop never breaks.
So the peer never
closes the connection
sends an empty line that compares to "" via the (incorrectly applied) == operator
sends a string consisting only of "q" plus a line terminator.
The normal way to write this loop would be:
while ((line = reader.readLine()) != null)
{
if (line.isEmpty() || line == "q") {
log("-- breaking the loop");
break;
}
printf("**%s%n", line);
}
But if the peer never closes the connection or sends the "q" there's no way this loop will ever exit. Are you sending anything that would produce either of those conditions?
disconnect the client from itself
This is meaningless. Please restate.
Related
I'm getting dead code warning in eclipse from the if(line == null) statement to the r.close() statement.
BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
int counter = 0;
while(true)
{
String line = r.readLine();
counter++;
if(line.contains(" = "))
{
String[] keyVal = new String[2];
keyVal[0] = line.substring(0, line.indexOf(" = ") - 1);
keyVal[1] = line.substring(line.indexOf(" = ") + 3);
buffer.add(keyVal);
}
else
{
new Exception("Invalid expression at line " + counter + " in file " + file.getPath()).printStackTrace();
}
if(line == null) // dead code here
{
break;
}
}
System.out.println("here is a dead code");
r.close(); // another dead code
You are operating on line with if(line.contains(" = ")). If line was null, a NullPointerException would be thrown, which you are not catching. Therefore, the break; statement can't be reached. If the if(line == null) statement is reached, it's not null. Logically, break; will never be executed, so it's unreachable. It appears that Eclipse is detecting this. Note that this will still compile with javac just fine; this is just Eclipse's warning.
Furthermore, if the break; is unreachable, then there is no way to end while(true), so anything beyond the while block is unreachable. So Eclipse warns on this too.
The usual way of reading a file line-by-line, checking the line for null to indicate end of the stream, is
String line;
while ( (line = r.readLine() ) != null)
{
// rest of processing here
}
It's not the cleanest code, with an assignment in the same expression as an equality check, but it's the usual way of doing this kind of read-and-check operation.
This way the while statement can end normally, and then there is no need to check for null later. That also makes any code following the while block reachable.
Put
if(line == null)
{
break;
}
before the
if(line.contains(" = "))
reason it is a dead code is because both if else statements can result in an exception , making any code after that a dead code.
My aim is to read the first element/term of each line from a given input file and then decide what to do (using an if-else construct) depending on what that first element is. I.e. if the first element/word happens to be "the" (as mentioned in the code below), then I have to skip that line and move to the next line.
I have written the following code till now but I am not sure on how to read only the first element of each line of the text file that I am passing as input.
public static void main(String[] args) {
BufferedReader br = null;
try {
String line;
br = new BufferedReader(new FileReader("input.txt"));
while ((line = br.readLine()) != null) {
System.out.println(line);
StringTokenizer stringTokenizer = new StringTokenizer(line, " ");
while (stringTokenizer.hasMoreTokens()) {
String term = stringTokenizer.nextElement().toString();
if (term.equals("the")) {
//Code on what to do depending on the first character of each line.
}
StringBuilder sb = new StringBuilder();
System.out.println(sb.toString());
}
}
System.out.println("Done!");
}
catch (IOException e)
{
e.printStackTrace();
}
finally {
try {
if (br != null)
br.close();
}
catch(IOException ex) {
ex.printStackTrace();
}
}
}
Below is the simple code that prints the as the output. you can use this and no need to create an extra array or use StringTokenizer.
String s = "The a an the abcdef.";
System.out.println(s.contains(" ") ? s.substring(0, s.indexOf(" ")) : s);
You can turn each term into an array of words via:
while((line = br.readLine()) != null){
System.out.println(line);
String word = line.split("\\s+")[0];
if(word.equals("the")){
//Code on what to do depending on the first character of each line.
}
StringBuilder sb = new StringBuilder();
System.out.println(sb.toString());
}
...
but I am not sure on how to read only the first element of each line of the text file that I am passing as input.
There are a couple of different solutions depending on your exact requirement.
You can read the entire line of data and then use the String.startsWith(...) method to test for the first word. Using this approach you don't tokenize all the data if you just want to skip the rest of the line. Then if you want to continue processing you can use the String.substring(...) method to get the rest of the data from the line.
You can use the Scanner class. The Scanner allows you to tokenize the input as you read the data from the file. So you can read the first word and then determine whether to skip the rest of the data or read the rest of the line.
StringTokenizer is considered as legacy class. It is only there for backward compatibility. Use split() on string to split the single string into array of strings/words.
String[] s = line.readLine().split(" ");
String firstWord = s[0]; // ->First word
So your code can be edited to
public static void main(String[] args)
{
BufferedReader br = null;
try
{
String line;
br = new BufferedReader(new FileReader("input.txt"));
while((line = br.readLine()) != null)
{
System.out.println(line);
String s = line.split(" "); // instead of StringTokenizer
if(s[0].equals("the"))
{
//Code on what to do depending on the first character of each line.
}
StringBuilder sb = new StringBuilder();
System.out.println(sb.toString());
}
System.out.println("Done!");
}
catch(IOException e)
{
e.printStackTrace();
}
finally
{
try
{
if (br != null)
br.close();
}
catch(IOException ex)
{
ex.printStackTrace();
}
}
}
Note:
Don't use startsWith(...) to check for the first word because it checks by character-wise instead of word-wise. If you want to check for the word the then the words there,their also returns true which might break your code.
Try to use split() instead of StringTokenizer from now onwards.
I have a server and client running on local server.
I read from the server this way:
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
public static String readResponse() throws IOException{
String response = "";
String line;
while((line = br.readLine()) != ""){
System.out.println("s: " + line);
}
return response;
}
And I get the response from server but the program stops and doesn't go anywhere from there:
Please enter option number: 1
c: MSGGET
s: 200 OK
s: Go for it now. The future is promised to no one.
And it just hangs here, when it is suppose to continue.
I also tried:
while((line = br.readLine()) != null){
It just keeps waiting. Is there anything maybe on the server that I have to change to tell the client that I am done transmitting data.
Please help! Thank you!
while((line = br.readLine()) != ""){
System.out.println("s: " + line);
}
return response;
}
Unless your peer is planning to transmit a blank line as an end-of-message sentinel, this loop is pointless, and it also compares Strings incorrectly.
And I get the response from server but the program stops and doesn't go anywhere from there.
It is waiting for an empty line that never arrives. And it is ignoring the end of stream condition.
while((line = br.readLine()) != null){
Now this loop is correct, but it won't exit until end of stream, which won't happen until the peer closes the connection.
It just keeps waiting.
That's what it's supposed to do.
Try this one :
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
public static String readResponse() throws IOException{
String response = "";
String line;
while((line = br.readLine()) != "" || (line = br.readLine()) != null)){
System.out.println("s: " + line);
}
return response;
}
if this is not working then you need to check if you are sending some special character on end of stream from server. Then apply check for that character.
I ended up using this:
while(!(line = br.readLine()).equals("exit")){
And I asked the person responsible for the server to print the following when he is done writing a response:
//this was initiated at the beginning of the program
out = new PrintWriter(socket.getOutputStream(), true);
out.println("exit");
This seems to works well for me so far!
Thank you everyone for your help!
I am trying to read lines of text from the console. The number of lines is not known in advance. The BufferedReader.readLine() method reads a line but after the last line it waits for input from the console. What should be done in order to avoid this?
Please see the code snippet below:
public static String[] getLinesFromConsole() {
String strLine = "";
try {
// Get the object of DataInputStream
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null)
strLine += line + "~"; //edited
isr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return strLine.split("~");
}
The below code might fix, replace text exit with your requirement specific string
public static String[] getLinesFromConsole() {
String strLine = "";
try {
// Get the object of DataInputStream
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null && !line.equals("exit") )
strLine += br.readLine() + "~";
isr.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return strLine.split("~");
}
When reading from the console, you need to define a "terminating" input since the console (unlike a file) doesn't ever "end" (it continues to run even after your program terminates).
There are several solutions to your problem:
Put the input in a file and use IO redirection: java ... < input-file
The shell will hook up your process with the input file and you will get an EOF.
Type the EOF-character for your console. On Linux and Mac, it's Ctrl+D, on Windows, it's Ctrl+Z + Enter
Stop when you read an empty line. That way, the user can simply type Enter.
PS: there is a bug in your code. If you call readLine() twice, it will skip every second line.
I'm writing a program that basically sends linux command through java and then prints back the output. It works fine if the output is one line only but for multiple lines output I can't figure out what I'm doing wrong. For example to check the memory usage I use the "free" command but it only returns lines 1 and 3. Here is my code:
if (clinetChoice.equals("3"))
{
String command = "free";
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
System.out.println("You Chose Option Three");
String line;
while ((line = reader.readLine()) != null)
{
output += line;
System.out.println(line);
line = reader.readLine();
}
}
When I run this it only returns:
total used free share buffers cached
-/+ buffers/cache: 6546546 65464645
Client Code:
while ((fromServer = input.readLine()) != null)
{
System.out.println("Server: " + fromServer);
if (fromServer.equals("Bye"))
break;
System.out.print("Enter your choice: ");
fromClient = stdIn.readLine().trim();
if(fromClient.equals("1"))
{
System.out.println("Client: " + fromClient);
output.println(fromClient);
}
if(fromClient.equals("2"))
{
System.out.println("Client: " + fromClient);
output.println(fromClient);
}
if(fromClient.equals("3"))
{
System.out.println("Client: " + fromClient);
output.println(fromClient);
}
if(fromClient.equals("4"))
{
System.out.println("Client: " + fromClient);
output.println(fromClient);
break;
}
}
You're calling readLine in both your loop test and the body of the loop. So for every iteration of the loop, readLine is called twice, and one of the results is discarded: it isn't printed or added to output. This matches the results that you describe.
This loop should be sufficient:
while ((line = reader.readLine()) != null)
{
output += line + System.getProperty("line.separator");
System.out.println(line);
}
If you're just trying to print the entire output once, and since you're collecting the output in your output variable, you can move the println out of the loop:
while ((line = reader.readLine()) != null)
{
output += line + System.getProperty("line.separator");
}
System.out.println(output);
Simply use this... You are calling the readLine() twice....
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
If you want to assign the data to output varible..then do this inside the while loop..
output = output + line;
I should point out that in addition to the comments re. using readline() twice, you should strictly consume stdout/stderr simultaneously. Otherwise you run the risk of blocking the process output since you're not consuming it. See this SO answer for more info.