Android strange bug while downloading a JSON - java

I need to download a JSON in a string, i'm almost sure the code isn't wrong, but there's something strange...
public boolean downloadJSON(){
json="";
try{
URL url = new URL(theURL);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null) {
json+=line;
}
in.close();
return true;
} catch (Exception e) {
return false;
}
}
Basically it open the buffer correctly, it read the json correctly and store it in the variable, it close the stream, then it go to the return true and... It randomly jump to the return false without sense, and while it's on the return false the Exception e is... null O.o
That make absolutely no sense, help me please D:!!!
In the end i solved it in this way:
public boolean downloadJSON(){
json="";
boolean out=false;
try{
URL url = new URL(theURL);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null) {
json+=line;
}
in.close();
out = true;
} catch (Exception e) {
}
return out;
}
Don't ask me how this is supposed to be correct if the first doesen't work, in my mind i still think the first should work :S
ADD: for Stephen C:
public boolean downloadJSON(){
json="";
try{
URL url = new URL("http://fapfapfap.altervista.org/conapo/conapo.php?n="+numeroPagina);
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null){json+=line;}
in.close();
return true;
}catch (Exception e) {
Log.d("ERRORE", e.getStackTrace().toString());
return false;
}
}

Try this:
URL url = new URL(theURL);
StringBuilder jsonResults = new StringBuilder();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStreamReader in = new InputStreamReader(conn.getInputStream());
// Load the results into a StringBuilder
int read;
char[] buff = new char[1024];
while ((read = in.read(buff)) != -1) {
jsonResults.append(buff, 0, read);
}
System.out.println(jsonResults.toString());

.... it still make no sense that my code jumped to the false without exception
You are misinterpreting the evidence:
public boolean downloadJSON(){
json = "";
try {
URL url = new URL(theURL);
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));
String line;
while ((line = in.readLine()) != null) {
json += line;
}
in.close();
return true;
} catch (Exception e) {
return false; // HERE
}
}
When you get to the statement I've labelled // HERE. It has happened >>because<< some exception has been thrown. There is absolutely no doubt about it. We don't know what exception it was, because your code simply throws away the exception object.
(Try adding e.printStacktace(); before the return false;)
I suspect it is either going to be a MalformedURLException, on a FileNotFoundException ... but it could be other things.
So what are your mistakes in this code?
1) Catching Exception is bad idea. The problem is that it catches too much. In addition to catching the exceptions that you (might have) expected at this point, it will catch all of the unexpected ones as well. For example, any NPEs or AIOOPEs or whatever arising from (hypothetical) bugs in your code.
In this case, you should probably catch the exceptions that are likely at this point; i.e. IOException.
2) Catching an exception and throwing away the stacktrace makes it hard to diagnose a problem. It is only advisable to "squash" an exception like that if you know (and can prove) that the exception is going to be what you expect.
3) Doing both 1) and 2) in the same piece of code is a REALLY bad idea.
4) Building a string like that is inefficient (or very inefficient ... if you are loading a really large document). Using a StringBuilder is much better.
Note however the 4) is peripheral to the problem you were having.

Related

Get last element of an array

through an API I get an array with a lot of different data. But I only need the last element.
The variable sb has the array in it. But i cannot access elements like that: sb[0] (for example)
If I print the variable sb it looks like that:
{"data":[[[1583596801195,279.52],[1583596814340,279.52],[1583596815535,279.44563849372383],[1583596816730,279.2060000000001],[1583596913525,279.2060000000001],[1583596914720,279.28824435146447],[1583596915915,279.52],[1583597211080,279.52],[1583597212275,279.52000000000004],[1583597213470,279.52],[1583597609015,279.52],[1583597610210,279.5199999999999],[1583597707005,279.5199999999999],[1583597708200,279.52000000000004],[1583597709395,279.52],[1583597806190,279.52],[1583597807385,279.52000000000004],[1583597993805,279.52000000000004]]]}
In this case, I only need the last element (279.52000000000004).
My code look like that:
URL url = new URL("the URL i get the data from");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
InputStream instream = con.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(instream));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(sb);
Sorry I am not experienced that experienced with programming. But I would really appreciate if someone could help me.
Thank you for your help.
If you need the last element only, you should not be appending the results.
Instead, replace the previous value stored.
String result = null;
String line = null;
try {
while ((line = reader.readLine()) != null) {
//sb.append(line + "\n");
result = line; // not appending, but replacing
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(result);
You can try this, replace this line "System.out.println(sb) with below code :
String s = new String(sb);
String d[] = s.split(",");
System.out.println(d[d.length -1].replaceAll("]", ""));
This would print the exact data you want i.e 279.52000000000004

Android BufferedReader does not read the whole response

I have a problem with reading a ULR response. On Android it only reads around the half of the response.
If I use the same code in a normal Java project everything works fine.
try {
String _output = null;
URL url = new URL("http://example.com");
BufferedReader buffer = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuilder everything = new StringBuilder();
String line;
while ((line = buffer.readLine()) != null) {
everything.append(line);
}
_output = everything.toString();
buffer.close();
System.out.print(_output);
} catch (IOException e) {
e.printStackTrace();
}
How do you know that it's only half of the response? If you rely on what is printed with System.out.println() then you should be aware that Logcat has a limitation that prevents it from printing more than 4,000 characters. Anything after that is truncated. To check how much of the response you have, you could print everything.length()first, ot see if you are in that situation.
You can look at this existing question on SO for reference, but there are many others.

Initialization in while block?

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.

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();
...
}

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