Impossible to read from ouput stream - java

I have a server that sends a String to a socket client. When I try to get the contents of the String from the client it wouldn't read it.
The server sends via:
output.write(res); output.flush(); // I checked res content and it is all good
and this the Client receiving:
public class Client {
public static void main(String[] args) throws IOException{
Socket connexion = new Socket(InetAddress.getLocalHost(), 33333);
BufferedReader input = new BufferedReader(
new InputStreamReader(connexion.getInputStream(), "8859_1"), 1024);
String res="";
while(input.readLine()!=null){
res += input.readLine()+"\n";
}
System.out.println(res);
}}
Suggestions please ? Thank you

The problem is that you are reading the next line and then disregarding it, and then trying to read the next line again. The second time you read the next line, there is no data because the first read has already consumed it:
while(input.readLine()!=null){
res += input.readLine()+"\n";
}
Try something like the following:
String line = null;
while((line = input.readLine()) != null) {
res += line + "\n";
}
As #JB Nizet mentioned, this is contingent upon the server actually sending a newline character to the client to terminate the message. As stated in the documentation for readLine():
Reads a line of text. A line is considered to be terminated by any one
of a line feed ('\n'), a carriage return ('\r'), or a carriage return
followed immediately by a linefeed.

Related

Read from socket until \r\n in Java

I want to implement a POP3 client. I know that in POP3 protocol, each message ends with \r\n. I want to write a recvuntil method in Java, which will be able to receive a whole message at once.
It super easy in Python:
def recv_all_until_ver3(s, crlf):
data = ""
while data[-len(crlf):] != crlf:
data += s.recv(1)
return data
However, when I tried to do the same in Java:
class JavaApplication1 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
// TODO code application logic here
String serverAddress = "interia.pl";
int port = 110;
Socket s = new Socket(serverAddress, port);
BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
String answer = "";
while (!answer.contains("\r\n")) {
answer = input.readLine();
System.out.println(answer);
}
}
}
It receives one message and hands instead of end itself. Is there any way to implement this method in Java? Can I just read characters one by one, instead of whole line until I find \r\n in my message? Thank you.
The Python code reads one octet at a time, immediately appends it to answer and signals it's done if at the current iteration answer ends with CRLF.
The Java code hangs because BufferedReader.readLine() returns the line content after stripping the line termination. At this point answer does not contain CRLF, so readLine() is called once again, and since the stream is not closed from the other end (your program would then throw a NullPointerException) and you have an infinite read timeout (you would see a SocketTimeoutException), it hangs, forever waiting for the next line.
The correct version is
Socket socket = connect(); // Implement this
Scanner scanner = new Scanner(new InputStreamReader(socket.getInputStream(), "ASCII"));
scanner.useDelimiter("\r\n");
String response = scanner.nextLine();
socket.close();
Notes:
always set a timeout on sockets.
you may want to account for multiline messages.
you can use the Scanner class (it accepts an InputStream as a constructor param ) and set the delimiter using useDelimiter method. to read messages that end with \r\n

ObjectInputStream.readObject skips last line of text file

Fairly simple question, I have a server with some file, lets call it serverFile.txt and I wish to send it line by line to some client. to achieve this, i wrote this simple code on the server side
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
while(line != null)
{
line = line + System.lineSeparator();
MMULogFileController.getOos().writeObject(line);
line = br.readLine();
System.out.println(line);
}
br.close();
where the MMULogFileController.getOos is the outputstream of the accepted socket.
It does indeed print all the lines of the file serverFile.txt
My problem is on the client side. This is the relevant code -
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
String line = (String)in.readObject();
File newLogFile = new File("newLog.txt");
PrintWriter ptofile = new PrintWriter(newLogFile.getName());
while(line != null)
{
ptofile.write(line);
try
{
line = (String) in.readObject();
}
catch(java.io.EOFException e)
{
line = null;
}
}
ptofile.close();
and it prints all the lines correctly into a new file on the client side, except for the very last line. I know it was sent from the server because it was printed, but on the client side it recieved null because it reaches EOF. Is there any way to deal with this?
Myself, I'd use a PrintStream to send the text out, and then read it in using either a BufferedReader or a Scanner. But having said that, if you insist on using an ObjectOutputStream, you should either flush or close it when done sending your file's text, and certainly close it when you're done using it.
Also, avoid this type of code:
catch(java.io.EOFException e)
{
line = null;
}
since this means that you're completely ignoring your exceptions. At least view the stack trace.

How to clear BufferedReader if it isn't empty [Java/Android]

I don't understand how to clear a BufferedReader. When I push button in Activity, the variable is set to 1 or 2. Depend on number change file in BufferedReader. When I push second time in buffer will be two files. How to tell BR to clear buffer before second will be upload. And vice versa, of course.
public List<String> getQuestionLinesList() {
String line;
List<String> lines = new ArrayList<String>();
Log.d(TAG, " Trying to get resourses");
Resources res = context.getResources();
try {
if (selectedBox == 1) {
bufferedQuestions = new BufferedReader(new InputStreamReader(res.openRawResource(R.raw.questions_list)));
} else if (selectedBox == 2) {
bufferedQuestions = new BufferedReader(new InputStreamReader(res.openRawResource(R.raw.questions_list_art)));
}
Log.d(TAG, "number i = " + Integer.toString(selectedBox));
while ((line = bufferedQuestions.readLine()) != null) {
lines.add(line);
Log.d(LINETAG, line);
}
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
Maybe you can try using a local variable in your method for BufferedReader not "bufferedQuestions" that you probably declared like a field in the class where that method : "getQuestionLinesList" belongs.
Add a carriage/ \n at the end of your files, then readLine() should be able to clear your BufferedReader.
JavaDocs for BufferedRead which states
public String readLine()
throws IOException
Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached

Read complete lines from file that is being continuously updated

I am writing a class that will read lines from a log file when it is updated.
I am using Apache VFS2 to get a method called when a file is updated. My main issue is I don't want to read the line from the file if the line is not complete yet, as in it does have a "\n" or "\r" line separator type character at the end. I think i have looked at all the Java libraries i can to read lines but they all discard the EOF and line termination information so I don't think I can use them.
Instead I am looking at reading it in byte by byte and then checking the result to then discard all stuff that comes after the last line separator. I was wondering what you folks thoughts on the best method for doing this is.
So for example:
2013-Jul-01_14:07:17.875 - Connection to Message Bus is reestablished<LF>
2013-Jul-01_14:07:17.875 - Connection to Message Bus is reestablished<LF>
2013-Jul-01_14:15:08.205 - No connection to Message Bus - reestablish before we can publish<LF>
2013-Jul-01_14:15:08.205 - NOT A REAL LINE PLEASE DONT READ
I want to read in the first 3 but not the fourth as it doesn't have a line feed or carriage return character ().
I have looked at Apache commons-io Tailer stuff but I cant tell if that will give me "incomplete" lines (and I realize I will have to ditch the VFS2 stuff to use it).
So psudo-code:
private void ingestFileObject(FileObject file) {
BufferedInputStream bs = new BufferedInputStream(file.getContent().getInputStream());
StringBuilder result = new StringBuilder();
while (bs.available() > 0) {
result.append((char) bs.read());
}
bs.close();
String resultString = result.toString();
//determine what part of resultString is after last carriage return/line seperate (using regex [\\r\\n]+?
//remove the offending part of String.
}
Or any other solutions completely ignoring my psudo-code are welcome at this point too...
Thanks
Is using Scanner help you?
Scanner scanner = new Scanner(file);
//block till there is some thing with a new line
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//do processing.
}
This is what I ended up doing:
BufferedReader bufReader = new BufferedReader(new InputStreamReader(file.getContent().getInputStream()));
StringBuilder result = new StringBuilder();
int readInInt = -1;
String charsSinceLastLineSep = "";
if (bufReader.ready()) {
while (-1 != (readInInt = bufReader.read())) {
char readInChar = (char) readInInt;
// if new line reset line buffer, otherwise add to buffer
if (readInChar == '\n' || readInChar == '\r') {
charsSinceLastLineSep = "";
} else {
charsSinceLastLineSep += readInChar;
}
result.append(readInChar);
}
bufReader.close();
// remove all characters added since last Carriage Return or NewLine was found indicating
// that line was not a complete log line
String resultString = (result.subSequence(0, (result.length() - charsSinceLastLineSep.length())).toString());

Chat client only printing 1 line at a time

I am writing a multithread chat server/client, I have been using SocketTest V 3 to test the server and it seems to be working fine but the client I have written only updates in the console when I write a new line, I am using my own client up against the socket test, and the socket updates every time something is written but my client does not
public class clientV2 {
public static final int PORT = 5019;
public static InetAddress host;
public static void main(String[] args) throws IOException {
try {
host = InetAddress.getLocalHost();
Socket socket = new Socket(host, PORT);
Scanner in = new Scanner(System.in);
Scanner inputFromServer = new Scanner(socket.getInputStream());
PrintWriter outputToServer = new PrintWriter(socket.getOutputStream());
while(true) {
if(inputFromServer.hasNext()) {
System.out.println(inputFromServer.nextLine());
}
String input = in.nextLine();
outputToServer.println(input);
outputToServer.flush();
}
} catch (Exception e) {
}
}
}
Your client calls nextLine() on its scanner, and this method, as it names indicates, returns the next line. So your client can't print anything until the complete next line is available.
Here's what the javadoc says about nextLine():
Advances this scanner past the current line and returns the input that
was skipped. This method returns the rest of the current line,
excluding any line separator at the end. The position is set to the
beginning of the next line.
Since this method continues to search through the input looking for a
line separator, it may buffer all of the input searching for the line
to skip if no line separators are present.
This is because System.out.println(inputFromServer.nextLine()); does exactly that. It waits for a full line and then prints that out. It will not print partial lines.
If the output is missing more than just the last partial line (line-break to line-break; line wraps don't count), look for the buffers along the way.
You can use an InputStreamReader to read single characters from the input stream (which is a byte stream). You can specify the charset in the constructor.
InputStreamReader inputFromServer =
new InputStreamReader(socket.getInputStream(), "UTF-8");
System.out.print((char) inputFromServer.read());

Categories

Resources