infinite while loop using bufferedreader - java

I am having a code to store the log files to a SD card in android. The following is the code.
process = Runtime.getRuntime().exec("logcat "+ LOG_TAG +":D *:S");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
StringBuilder log = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
//do something over here
}
It is running an infinite loop.
Any help.

As logCat never ends, you might try to force an end when InputStream.available() == 0.
I did this using wrapping the original InputStream in an ImpatientInputStream.
As at the very first start available might be 0 because of the non-blocking nature, you might add a flag whether something read already.
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(
new ImpatientInputStream(process.getInputStream())
));
public class ImpatientInputStream extends InputStream {
private final InputStream in;
private boolean eof;
public ImpatientInputStream(InputStream in) {
this.in = in;
}
#Override
public int read() throws IOException {
if (eof) {
return -1;
}
if (available() == 0) {
eof = true;
return -1;
}
return in.read();
}
}

logcat never stops, it waits for the next line to display, so readLine() blocks while waiting for the next input from the process.
You can however redirect the output of the command directly with -f filename as explained here.
This answer has everything you need.

You can provide timestamp/time period in while loop. Below sample will make this more clear
Sample :
while (System.currentTimeMillis() < end_time) {
//do your stuffs here
while ((line = bufferedReader.readLine()) != null) {
//do something over here
}
}

Related

process.waitFor is stuck

In below java code, I see that process.waitFor() seems to not exit. I have set processBuilder.redirectErrorStream(true); which should help me to redirect error with standard output and am reading the inputStream in method readProcessOutput. I thought when we read all the output and error streams the process should exit. But currently its struck. Can I please know how to solve this?
Also, I am using which sets standard I/O to be the same as those of the current Java process.
...
ProcessBuilder processBuilder = new ProcessBuilder().inheritIO().command("sh",
"test.sh");
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
List<String> results = readProcessOutput(process.getInputStream());
setExitCode(process.waitFor());
...
private List<String> readProcessOutput(InputStream inputStream) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream), 1);
List<String> lines = new ArrayList<>();
String line;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
inputStream.close();
bufferedReader.close();
return lines;
}
public int getExitCode() {
return exitCode;
}
private void setExitCode(int exitCode) {
this.exitCode = exitCode;
}

File convertion not working inside a for loop

I need to ftp download and convert a file to a string, this way:
public static boolean leArquivos(String inicioArquivo) {
try {
FTPClient mFtp = new FTPClient();
mFtp.connect(FTPHOST, PORTA);
mFtp.login(USUARIO, SENHA);
FTPFile[] ftpFiles = mFtp.listFiles();
int length = ftpFiles.length;
for (int i = 0; i < length; i++) {
String nome = ftpFiles[i].getName();
String[] itens = nome.split("_");
boolean isFile = ftpFiles[i].isFile();
String arquivo_id = itens[0];
if (isFile && (arquivo_id.equals(inicioArquivo))) {
// the follow lines work if outside the for loop
InputStream inStream = mFtp.retrieveFileStream(nome.toString());
String arquivoLido = convertStreamToString(inStream);
String[] arquivoLidoPartes = arquivoLido.split("#");
Retorno.adicionaRegistro(nome, arquivoLidoPartes[0], arquivoLidoPartes[1], false);
}
}
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
This gonna read a 'inicioArquivo_anything.txt' and put into a string.
FTP and Registro.adicionaRegistro works fine.
If I move the 4 lines that are inside the 'if' to outside the 'for' loop, it works for a single file.
I need perform the action for several files.
Sorry about bad english (and bad Java too)...
EDIT
Worked this way
The convertion code:
private static String convertStreamToString(InputStream is, FTPClient mFtp) throws IOException { // added the client
BufferedReader r = new BufferedReader(new InputStreamReader(is));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
r.close(); // close stream
is.close(); // close stream
mFtp.completePendingCommand();
return total.toString();
}
And changed this:
String arquivoLido = convertStreamToString(inStream, mFtp);
inStream.close();
As written in the API doc, you have to close the stream (after the conversion) and call the completePendingCommand method to finalize and check the status of the transfer :
FTPClient.html#retrieveFileStream
And, in all you programs, the basics: don't forget to close the Streams !!

Java Process can't get ErrorStream message

everyone, I have a process that needs to get standard output and log/error/exception output from the subprocess. The standard output is fine, but I can't get ErrorStream, therefore the program is stuck there because of that. Here is my simple code. There is nothing magic, but why can't I get the error stream here? Thanks for looking at it.
BufferedReader standard =
new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader error =
new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = standard.readLine()) != null) {
System.out.println(line);
}
while ((line = error.readLine()) != null) {
System.out.println(line);
}
Now, as suggested, i used two threads to process the output and error streams, but still had the same problem, as follows. Can anybody give me some insights? Thanks.
ProcessBuilder pb = new ProcessBuilder(listArgs);
pb.redirectErrorStream();
Process process = pb.start();
StreamThread output = new StreamThread(process.getInputStream());
StreamThread error = new StreamThread(process.getErrorStream());
output.start();
error.start();
while (true) {
try {
output.join();
break;
}
catch (InterruptedException ie) {
ie.printStackTrace();
}
}
The definition of the StreamThread:
public static class StreamThread extends Thread{
private InputStream input = null;
public StreamThread(InputStream in){
input = in;
}
String line = null;
public void start(){
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
try{
while( (line=reader.readLine()) != null ){
System.out.println(line);
}
reader.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
Look at your loops:
while ((line = standard.readLine()) != null) {
System.out.println(line);
}
while ((line = error.readLine()) != null) {
System.out.println(line);
}
You're going to keep reading from the output stream until it's finished - which is likely to be when the process terminates. Only then do you start reading the error stream.
You should probably put at least one of these into a different thread, so you can read from both streams at the same time.

Java - reading file as binary with readLine

I have a Ruby code that reads file line-by-line and checks if it needs to read the next line to some block or it should handle that block and continue reading file parsing each line.
Here's it:
File.open(ARGV[0], 'rb') do |f|
fl = false
text = ''
f.readlines.each do |line|
if (line =~ /^end_block/)
fl = false
# parse text variable
end
text += line if fl == true
if (line =~ /^start_block/)
fl = true
end
end
end
E.g. i need the file to be opened for reading as binary and still i need a readLine method.
So, the question is: how can i do exactly the same with Groovy/Java?
You can use java.io.DataInputStream which provides both a readLine() method and readFully(byte[]) and read(byte[]) methods.
Warning: The JavaDoc for readLine says, it is deprecated and that the encoding might be inappropriate (read details in JavaDoc).
So think twice about your real requirements and if this is a suitable trade-off in your case.
If you have line formatted text, that's not binary IMHO. That's because true binary can have any byte, even new line and carriage return which would create false breaks in the code.
What you could mean is you have text where you want to read each byte without encoding or possibly mangling them. This is the same as using ISO-8859-1.
You can try
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(filename), "ISO-8859-1"));
StringBuilder sb = new StringBuilder();
String line;
boolean include = false;
while((line = br.readLine()) != null) {
if (line.startsWith("end_block"))
include = false;
else if (line.startsWith("start_block"))
include = true;
else if (include)
sb.append(line).append('\n'); // new lines back in.
}
br.close();
String text = sb.toString();
Maybe something like this:
public final class Read
{
private static final Pattern START_BLOCK = Pattern.compile("whatever");
private static final Pattern END_BLOCK = Pattern.compile("whatever");
public static void main(final String... args)
throws IOException
{
if (args.length < 1) {
System.err.println("Not enough arguments");
System.exit(1);
}
final FileReader r = new FileReader(args[0]);
final BufferedReader reader = new BufferedReader(r);
final StringBuilder sb = new StringBuilder();
boolean inBlock = false;
String line;
while ((line = reader.readLine()) != null) {
if (END_BLOCK.matcher(line).matches()) {
inBlock = false;
continue;
}
if (inBlock)
sb.append(line);
if (START_BLOCK.matcher(line).matches())
inBlock = true;
}
System.out.println(sb.toString());
System.exit(0);
}
}

How to see if a Reader is at EOF?

My code needs to read in all of a file. Currently I'm using the following code:
BufferedReader r = new BufferedReader(new FileReader(myFile));
while (r.ready()) {
String s = r.readLine();
// do something with s
}
r.close();
If the file is currently empty, though, then s is null, which is no good. Is there any Reader that has an atEOF() method or equivalent?
The docs say:
public int read() throws IOException
Returns:
The character read, as an integer in the range 0 to 65535 (0x00-0xffff), or -1 if the end of the stream has been reached.
So in the case of a Reader one should check against EOF like
// Reader r = ...;
int c;
while (-1 != (c=r.read()) {
// use c
}
In the case of a BufferedReader and readLine(), it may be
String s;
while (null != (s=br.readLine())) {
// use s
}
because readLine() returns null on EOF.
Use this function:
public static boolean eof(Reader r) throws IOException {
r.mark(1);
int i = r.read();
r.reset();
return i < 0;
}
A standard pattern for what you are trying to do is:
BufferedReader r = new BufferedReader(new FileReader(myFile));
String s = r.readLine();
while (s != null) {
// do something with s
s = r.readLine();
}
r.close();
the ready() method will not work. You must read from the stream and check the return value to see if you are at EOF.

Categories