Initialization in while block? - java

Isn't there a cleaner way of doing the following (eliminating the need for initializing line prior to the while block)? It just seems unnecessary to intialize a variable prior to its usage instead of doing something like while ((String line = br.readLine) != null) {}. If not, why not?
BufferedReader reader = null;
try
{
File file = new File("sample-file.dat");
reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}

No, you cannot avoid initializing the variable. However, you can use Try-With-Resources to make it a lot cleaner.
try (BufferedReader reader = new BufferedReader(new FileReader("sample-file.dat"))) {
String line;
while ((line = reader.readLine()) != null)
{
System.out.println(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}

Just adding this for completions sake, if anyone is using Java 8, you have access to the Stream API. Using this you can just simply do the following:
BufferedReader reader = new BufferedReader(...);
reader.lines().forEach(System.out::println);
And if you're wondering, the code under the hood that produces this does check for null lines.

No you can't declare (and use) a variable in the while loop expression evaluation step. But, you can eliminate the finally block by using a try-with-resources
try (
File file = new File("sample-file.dat");
BufferedReader reader = new BufferedReader(new FileReader(file));
) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}

No, you can't declare a variable inside the condition definition except in a for loop. Can't really say why - perhaps because the condition is not supposed to be somewhere you initialize things, whereas a for initialization step is.
But anyway, especially in cases where the loop conditions are complicated, some coders prefer to use
while (true) {
String line = reader.readLine();
if ( line == null )
break;
System.out.println(line);
}
But it's really a matter of style.

Related

Getting data from php file in my Android java class using bufferreader

I am getting data from php file in android java class using
BufferedReader reader = new BufferedReader(new
InputStreamReader(con.getInputStream()));.
This code is in my php file is
echo "abc";
echo "xyz";
This is the code of my java file.
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
Complete_line = null;// Read Server Response
while ((line = reader.readLine()) != null) {
System.out.println(line);
break;
}
But when I read from Buffer reader it will read a whole one line, or it will print "line" string as "abcxyz". But I want them as two lines as they are two different lines in the PHP file.
try this,
BufferedReader reader = null;
StringBuffer response = new StringBuffer();
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "";
while ((line = reader.readLine()) != null) {
response.append(line+"\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In PHP, unless you seperate the 2 lines a a newline character \n, the two echos are the same. To seperate echos into different lines, you need to end the strings with \n, like this:
echo "abc\n";
echo "xyz\n";

How to rewrite empty while block

I have instantiated a BufferedReader to read an input stream. It has a boolean ready() method that returns false until the reader can be read. Now I have
BufferedReader br = new BufferedReader(new InputStreamReader(myProcess.getInputStream()));
try {
while (!br.ready()) {
}
String line = br.readLine();
...
} catch (IOException e) {
...
What PMD warns me about is the empty while block and I guess PMD is right. How can I rewrite the code?
you don't want to use ready(). readLine() is a blocking call, just call it.
the standard usage of BufferedReader is:
String line = null;
while((line = br.readLine) != null) {
// do stuff with line here ...
}
You could try this:
BufferedReader br = new BufferedReader(new InputStreamReader(myProcess.getInputStream()));
try {
String line;
while ( null != (line = br.readLine() )) {
...
}
...
} catch (IOException e) { ... }
A way to rewrite it is
while(!br.ready());
But a more readable way to do this is to read only when the buffer is ready
while(br.ready()){
String line = br.readLine();
...
}

Manipulate big Textfiles in Java

I was wondering how do you manipulate big Textfiles in Java, if we assume that the Filesize is larger than the memory. I googled that topic and it shows that most people recommend java.niofor such a task.
Unfortunately I haven't found any documentation on how to manipulate the File. For example read every Line, modify it, write it. I tried something like this, but this doesn't work:
FileChannel fileChannel = null;
try {
fileChannel = new RandomAccessFile(file, "rw").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(256);
while (fileChannel.read(buffer) != -1) {
buffer.rewind();
buffer.flip();
String nextLine = buffer.asCharBuffer().toString();
if (replaceBackSlashes) {
nextLine = nextLine.replace("\\\\", "/");
}
if (!(removeEmptyLines && StringUtils.isEmpty(nextLine))) {
buffer.flip();
buffer.asCharBuffer().put(nextLine);
}
buffer.clear();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fileChannel != null) {
try {
fileChannel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
So what are your recommendations? Also the String nextline, doesn't match anything in my File. Maybe I need to set the encoding?
Line by line. Something like this ...
public static void main(String[] args) throws Exception {
File someFile = new File("someFile.txt");
File temp = File.createTempFile(someFile.getName(), null);
BufferedReader reader = null;
PrintStream writer = null;
try {
reader = new BufferedReader(new FileReader(someFile));
writer = new PrintStream(temp);
String line;
while ((line = reader.readLine())!=null) {
// manipulate line
writer.println(line);
}
}
finally {
if (writer!=null) writer.close();
if (reader!=null) reader.close();
}
if (!someFile.delete()) throw new Exception("Failed to remove " + someFile.getName());
if (!temp.renameTo(someFile)) throw new Exception("Failed to replace " + someFile.getName());
}
Kudos to xagyg for a nice, clean answer! The following just didn't fit into a comment:
If you're running Java 7 already, you can save a lot of boilerplate code by using try-with-resources for the processing loop:
File source = ...
File target = ...
try (BufferedReader in = new BufferedReader(new FileReader(source));
PrintStream out = new PrintStream(target)) {
String line;
while ((line = in.readLine()) != null) {
// manipulate line
out.println(line);
}
}
// no catch or finally clause!
No more of that initalize-to-null-try-catch-finally-close-if-not-null mess, Java will take care of that for you now. Less code, less potential to forget or screw up that crucial call to close().

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.

Closing BufferedReader and InputStreamReader

This piece of code is creating memory leak issues cause of BufferedReader and InputStreamReader which I think might be happening cause of some exceptions. How should I change it?
try{
URL url = new URL(sMyUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
while ((str = in.readLine()) != null) {
jsonString += str;
}
in.close();
}catch(Exception e){
}
It would be safer to close your stream using a try..finally block. You might also use a StringBuilder as it is designed for concatenating strings. You should also avoid catching Exception and doing nothing with it. Also, your code is concatenating lines without any line-breaks. This may well not be what you want, in which case append("\n") when you read each line in.
Here's a version with those modifications:
StringBuilder json = new StringBuilder();
try {
URL url = new URL(sMyUrl);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
try {
String str;
while ((str = in.readLine()) != null) {
json.append(str).append("\n");
}
} finally {
in.close();
}
} catch (Exception e) {
throw new RuntimeException("Failed to read JSON from stream", e);
}
The code isn't pretty but won't be creating a memory leak. I suggest you use a memory profiler to determine where your memory is being used. Otherwise you are just guessing even if you have ten + years experience performance tuning in Java ;)
A better alternative is to use Java 7
URL url = new URL(sMyUrl);
try(BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
while ((str = in.readLine()) != null) {
jsonString.append(str).append("\n");
}
}
If you have Java 6 or older you can use.
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
try {
while ((str = in.readLine()) != null) {
jsonString.append(str).append("\n");
}
} finally {
in.close();
}

Categories