I am building a simple client-server program , I have in main :
FTPClient ftp = new FTPClient("www.kernel.org");
ftp.getReply();
ftp.sendCommand("USER " + "anonymous");
ftp.getReply();
ftp.sendCommand("PASS " + "anonymous");
ftp.getReply();
String com="";
while (!com.equalsIgnoreCase("quit")){
System.out.println("Enter your Commands . or Enter quit");
BufferedReader Keyboard = new BufferedReader(new InputStreamReader(System.in));
com = Keyboard.readLine();
ftp.sendCommand((com));
ftp.getReply();
System.out.println("===============");
}
ftp.close();
the problem is in the getReply() function, this function is :
public void getReply() throws IOException {
String line="";
while (br.ready())
{
line = br.readline();
System.out.println(line);
System.out.flush();
}
}
br is a BufferedReader.Now all the problem is that when the program starts it doesn't show the welcome message from the Server until I press Enter or any command, when I Debug the program Step by Step every thing is working perfectly.So is the problem in the readline and I should use something else or what?
The problem is likely that the end of the server response does not contain a newline character. The BufferedReader's readLine method will block until a line of data is received, where "a line" consists of some characters followed by a newline character (or the end of the stream). Consequently, the readLine call will not return if no newline is received.
In this situation then, the BufferedReader isn't doing you any good. You'd be better off using the underlying Reader yourself, reading into an array and emitting the output as soon as it comes in, such as the following:
final char[] buffer = new char[256]; // or whatever size you want
int nRead;
while ((nRead = reader.read(buffer)) != -1)
{
System.out.println(new String(buffer, 0, nRead));
System.out.flush();
}
The condition in the while loop there might look confusing if you're not used to it before, but it combines the read operation (which reads into the buffer) with the check that the end of the stream has not been reached. Likewise, the construction of the String within the while loop takes into account the fact that the buffer may not have been filled entirely, so only as many characters as were supplied are used.
Note that this particular snippet keeps looping until the stream is empty; you may wish to add another exit condition in your particular case.
Related
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
If I get the standard input from pipe like this, it is ok.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while((input=reader.readLine())!=null)
{
...
}
But if I write my program like this,the BufferedReader can only get a half standard input from the pipe. The pipe will stop somewhere but the position is not certain.
And also every time I input manually line by line. The program is fine. But if I suddenly input a thousand lines. It will only output the result of the first line. I used to input only manually before so this is the first time I met this problem. I thought this two should be the same.
while(true)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
if((input=reader.readLine())==null)
{
break;
}
...
}
The BufferedReader will read more than one line, so the next invocation can get more data without going through the operating system, which enhances performance.
If you delete the BufferedReader and create a new one, all the data that is already stored in the first instance is lost.
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String input;
String completeInput = "";
while(true)
{
if((input=reader.readLine())==null)
{
break;
}
//here you need to do something with your input
//for example
completeInput+=input;
}
//here you have complete input string in complete input
The difference between these 2 ways of coding is very simple.
First way:
you have declared buffer reader outside the while loop like below
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
and hence for each iteration of while loop, it keeps pointing to the single same console
and hence it reads all data from the console so is the output in right way as expected
second way:
you have declared buffer reader inside while loop like below
while(true)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
//rest of the code
}
here for each iteration it creates new reader pointing to new console because of System.in assigned to reader for every while loop iteration.
so when it reads first time it reads all your lines and execute else block and prints first line because of readLine method gets only one line at a time.
and during second iteration of while loop , it points to new console and new console will not have any data so it breaks the while loop.
but if you enter line by line each while loop iteration points to new console and you enter it to new console each time and hence it prints correctly.
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());
I am creating a java console application and i need to use a notepad (txt) file to store PIN, AccountNo and Balance.
When the user enters the PIN (from BufferedReader) it should get validated from the notepad file and login to thge system. However, the code fragment which I used below only displays Enter PIN, and when i click on Enter, the program exits.
Could you please tell me what is the mistake which I have done here?
BufferedReader getIt = new BufferedReader(new InputStreamReader(System.in));
String userPIN = "";
try {
// Open the file that is the first command line parameter
FileInputStream fstream = new FileInputStream(
"D:\\Studies\\BCAS\\HND\\Semester 1\\Programming Concepts\\Assignment\\AccountInfo.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
System.out.println("Enter PIN");
userPIN = getIt.readLine();
while ((strLine = br.readLine()) != null) {
// Print the content on the console#
if (userPIN.equals(strLine)) {
System.out.println("You have login!");
}
}
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
There are quite a few reasons why the program can simply terminate, or appear to be successful in program execution (and hence terminate successfully without doing any useful work):
The contents of the file are read, but if the end of the stream has been reached, then the code simply does not handle the case gracefully (or even consider handling it). Specifically, the line while ((strLine = br.readLine()) != null) can result in a scenario where the body of the loop is not executed.
The else condition is absent inside the body of the while loop. If none of the entries provided by the user input match the contents of the file, the code does not handle the condition, and the result is ambiguous. For all practical purposes, it appears that login is successful if the provided PIN is not present in the file.
Avoid unnecessary decoration of Readers and Streams. BufferedReader in
= new BufferedReader(new FileReader("foo.in")); is sufficient to read character data from files, and it does provide the read and readline methods to use.
PS: It is recommended that you learn to program defensively, especially when dealing with files and streams. That would help isolating cases in your code that would result in ambiguious/vague conditions.
File.ReadAllLines would be more convenient in your case.. Wouldn't be wrong to introduce a user class either if your going the good ol' oop way.
If you want to do this by yourself, StreamReader (which takes FileInfo) is a good way to go. Try to create it by using the using statement (:)) which makes cleans up after your done.
I tried to ask this question earlier, but I was unclear in my question. Java BufferedReader action on character?
Here is my problem.. I have a BufferedReader set to read from a device. It is reading well. I have it set to
if (Status.reader.ready()) {
Lines = Status.reader.readLine();
}
if (Lines.contains(">")) {
log.level1("ready to send data")
}
Buffered reader does not report the > until I've sent more data to the device. The problem is that when reader contains > it is not reporting ready. It holds onto the > until I input more data.
I tried the following and it returns nothing. It does not even return the log.level0()
Lines = ""
try {
Lines = Status.reader.readLine();
} catch (IOException e) {
Log.level0("Attempted to read blank line");
}
Here is the actual data sent:
^M^M01 02 F3^M00 01 F3 3E^M>
But BufferedReader ignores the > until more data has been sent then get a result like this:
>0102
When I check the actual data from the device from the command prompt, it returns what I'd expect, the > is present.
BufferedReader will not give me the >. Is there some way I can check for this char otherwise?
The BufferedReader.readLine() method reads data a line at a time. That is, it will attempt to read characters until it sees an end-of-line sequence (e.g. "\n", "\r" or "\r\n") or the end of stream.
If your input data is not line oriented, then you should not be using readLine() to read it. I suggest that you do your own record / message extraction; e.g.
BufferedReader br = ...
StringBuilder sb = new StringBuilder(...);
int ch = br.read();
while (ch != -1 && ch != '>') {
sb.append((char) ch);
ch = br.read();
}
String record = sb.toString();
Check this:
http://download.oracle.com/docs/cd/E17476_01/javase/1.5.0/docs/api/java/io/BufferedReader.html
I recommend that you use the function public int read() instead.
At google you can find a lot of examples1
With those F3s in there it looks to me like your data isn't even character-oriented let alone line-oriented. Is your device really Unicode-compliant?
I would use a BufferedInputStream.