简体   繁体   中英

How to read CR LF line with BufferedReader?

I am trying to create a simple java server application, but I am struggling to read the user's input with BufferedReader correctly. The problem is that the line delimeter is CR LF ("\\r\\n") only - so I can't use readLine() standard method. Therefore, I tried to implement my own method:

private String readCRLFLine(BufferedReader in) {

    StringBuilder result = new StringBuilder();
    char cr = 'a'; // initialize cr
    char lf;

    try {
        while (((lf = (char) in.read()) != '\n') && (cr != '\r')) {
            cr = lf;
            result.append(lf);
        }
        result.deleteCharAt(result.length() - 1); // delete \r from the result
    } catch (IOException ex) {
        // handle the exception here
    }

    return result.toString();
}

Now, when I try to get and print the result:

while ((userMessage = readCRLFLine(inputStream)) != null) {
        System.out.println(userMessage);
        break;
}

...it only prints the sequence of characters to the first break line character ("\\r" or "\\n") and the rest of the input is read by the second call of method readCRLFLine(inputStream) - which should already read other input.

I want to be able to handle inputs like:

"abc\\rabc\\n\\r\\abc\\r\\n"

In this case userMessage should be:

"abc\\rabc\\n\\r\\abc"

I can't use Scanner and it's "useDelimeter("\\r\\n")" method, because I need to set up TIMEOUT with "clientSocket.setSoTimeout(TIMEOUT)" and from what I know, this is not possible with Scanners.

What is wrong with my "readCRLFLine" method? Is there any other solution to this problem?

Any help would be appreciated.

Your method is incorrect because the while condition is not what you actually need.

It says "As long as the currently read character is different than \\n and the previous character is different than \\r , continue reading".

But that means that when you read a \\n , that condition is false , because lf != '\\n' is false. So it will stop on the first \\n . It will also stop on any character that follows a \\r , because then cr != '\\r' is going to be false making the combined condition false.

You want to stop the loop when the current character is \\n and the previous character is \\r . That means your while condition is supposed to be ! ( lf == '\\n' && cr == '\\r') ! ( lf == '\\n' && cr == '\\r') .

Now pay attention to the DeMorgan law: "not (A and B)" is equivalent to "not A OR not B". You mistakenly decided to use AND instead of OR. Change your condition to:

while (((lf = (char) in.read()) != '\n') || (cr != '\r')) {
   ...
}

By the way, you should probably check that the value you read from in is not negative before you convert it to char and compare it. A negative value indicates that the client closed the connection, and you'll get into an endless loop if that happens.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM