Exception thrown on assignment of an array to another array - java

I have a function which fetches a certain website's HTML code. Eventually that function will return the whole page as an array. I am trying to save the page in another array, but it will always throw an exception (ArrayIndexOutOfBoundsException) for some reason.
I am not sure if I am just missing something elementary or if it's more than just that. To give you some of my code:
protected String[] doInBackground(String... login)
{
String[] page = new String[1024];
try {
page = executeHttpGet(); //THIS IS WHERE IT FAILS
} catch (Exception e) {
page[0] = "Error";
}
return page;
}
public String[] executeHttpGet() throws Exception {
URL u;
InputStream is = null;
DataInputStream dis;
String s;
int i = 0;
String[] page = new String[1024];
addSecurityException();
Authenticator.setDefault(new MyAuthenticator(activity));
try {
u = new URL("https://myurl.com");
is = u.openStream();
dis = new DataInputStream(new BufferedInputStream(is));
while ((s = dis.readLine()) != null) {
if (s.toString().length() > 10)
{
page[i] = s.toString();
i++;
}
}
} catch (IOException ioe) {
}
finally {
try {
is.close();
} catch (IOException ioe) {
}
}
return page;
}
}
Does anyone have any ideas why I am not able to assign the returned array to the array in doInBackground()? Help would be greatly appreciated.

Your catch-blocks are empty, which is a terrible idea, because you'll get no information when something goes wrong.
You don't need to initialize page on its declaraton, when you re-assign it two lines below (you'll have to change the catch-block to create a new array, 'though).
Have you checked that your URL doesn't return more than 1024 lines?
You don't need s.toString() when s is a String, because it will just return s.
When analyzing an exception, you should look at the whole stacktrace to find out where exactly the problem occurs.
When asking about an exception you should post the whole stacktrace!
When you have an unspecified number of elements List is a more flexible and easier-to-use alternative to arrays. Generally speaking, arrays are quite low-level and there's barely a reason to use them directly (they are very useful for building List implementations).

Related

Block of code is not touched

I'm building a small application in Java, small game mechanics but nothing serious. I have a class which purpose is to fetch data from a file. But when I declare the two classes to read from it the program justs ignore everything and continues. As a result, when I try to access the respective lists it gives me null pointer exception. Code of the method that fetches data below:
public void getData(int l, player tmp, level le) {
String[] dataPlayer;
String[] dataLevel;
try {
//FileReader f = new FileReader(this.levelPath.concat(Integer.toString(l)));
File f = new File(this.levelPath.concat(Integer.toString(l)));
BufferedReader buff = new BufferedReader(new FileReader(f));
System.out.println("Reached");
boolean eof = false;
while (!eof) {
String b = buff.readLine();
if (b == null)
eof = true;
else {
if (b.contains("player")) {
dataPlayer = b.split("-");
for (int i = 0; i < dataPlayer.length; i++) {
if (i == 0)
continue;
items it = new items(dataPlayer[i]);
tmp.setInventory1(it);
}
}else if (b.contains("level")) {
dataLevel = b.split("-");
for (int i = 0; i < dataLevel.length; i++) {
if (i == 0)
continue;
items it = new items(dataLevel[i]);
le.setSpecific(it);
}
}
}
}
}catch (IOException i) {
i.getMessage();
}
}
File contents of the file "levelData1":
player-hat
player-flashlight
level-flower
level-rock
player-adz
The problem with this particular problem was the path, it needed the absolute like that /home/toomlg4u/IdeaProjects/javaProject/src/Data/levelData.
You're doing a lot of things inside that try/catch that may not throw an IOException. If you get any other exception, it's not going to be caught. Depending on what other exception handling you have in place, that may cause weird behavior. For debugging, you could catch all exceptions, and see if you're getting something else.
If you want to remain to your loop code then you can refactor your code to look like this one:
public void getData(int l, player tmp, level le) {
try (BufferedReader buff = new BufferedReader(new FileReader(new File(this.levelPath + l)))) {
String b;
while ((b = buff.readLine()) != null) {
if (b.contains("player")) {
String[] dataPlayer = b.split("-");
items it = new items(dataPlayer[1]); //because you know that you will have an array with only 2 elements
tmp.setInventory1(it);
}else if (b.contains("level")) {
String[] dataLevel = b.split("-");
items it = new items(dataLevel[1]); //because you know that you will have an array with only 2 elements
le.setSpecific(it);
}
}
}catch (IOException e) {
e.printStackTrace();
}
}
It is a little bit better than that you have, easier to debug and to read. I advice you to read about try with resources.
As a rule of thumb, each time when you open a stream you have to close it. When you don't open it yourself then don't close it.
This is how it should look like a decent program in Java:
private Stream<Items> asStreamOfItems(String line){
return Stream.of(line.split("-")).skip(1).map(Items::new);
}
public void parseFile(String pathToTheFile) throws IOException {
List<String> lines = Files.readAllLines(Paths.get(pathToTheFile));
List<Items> players = lines.stream().filter(line -> line.contains("player")).flatMap(this::asStreamOfItems).collect(Collectors.toList());
List<Items> levels = lines.stream().filter(line -> line.contains("level")).flatMap(this::asStreamOfItems).collect(Collectors.toList());
........
}
In this case all your weird errors will vanish.
After you edited the post I saw your file content. In this case the code should look like this one:
class Items {
private final String name;
public Items(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static Items parse(String line) {
return new Items(line.split("-")[1]);
}
}
public void parseFile(String pathToTheFile) throws IOException {
List<String> lines = Files.readAllLines(Paths.get(pathToTheFile));
List<Items> players = lines.stream().filter(line -> line.contains("player")).map(Items::parse).collect(Collectors.toList());
List<Items> levels = lines.stream().filter(line -> line.contains("level")).map(Items::parse).collect(Collectors.toList());
..............
}
Btw, you broke a lot of Java and general programming rules like:
using continue is a bad practice. It should be used only in extreme cases because it makes the code difficult to read.
the class name in Java should be in the CamelCase notation
one method should have only one responsibility
DON'T mutate the object inside of a method (example: tmp.setInventory1(it);) very very very bad practice
when you work with streams use try with resource or try/catch/finally to close your stream after you finish the reading.
Before jumping to write code explore the JAVA IO SDK to look for better methods to read from files

File IO with android.os.memoryfile

I am trying to write to a file using android.os.memoryfile and then read from the same file. I write to the file in one method and read from another method, all in the same class. I can write fine but When I read the file I get lines of a symbol instead of the content I had written to the file. It seems that the read method is not reading the file I had written to.
If I put code to write and read the file in same method, it seems to work fine. Reading file outputs the string I had written.
Here is my code:
public class FileActivity extends Activity {
MemoryFile memFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
memFile = new MemoryFile("MemoryFileTest", 1000000);
} catch (IOException e) {
e.printStackTrace();
}
}
public void readFile () {
StringBuffer strBuffer = new StringBuffer();
try {
InputStream in = memFile.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String inputString;
while ((inputString = reader.readLine()) != null) {
strBuffer.append(inputString + "\n");
}
in.close();
reader.close();
Log.d(TAG, strBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile () {
String example = "This is an example";
byte[] bytes = example.getBytes();
try {
OutputStream out = memFile.getOutputStream();
out.write(bytes);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
In the above code, the MemoryFile is declared in top of class, and initialized in onCreate() method. I am then trying to write and read with that one MemoryFile.
What am I missing here?
I've not used MemoryFile and only starting learning about it for this question. I looked at the source code from within Android Studio. I couldn't find the raw source on the Web. The grepcode version is here. From my experiments and looking at the source code, it's clear that the end-of-file concepts we expect from file-based streams don't apply to a MemoryFile. The end-of-file is based on the length specified in the MemoryFile constructor, not the number of bytes that have been written to the file. Given this, the behavior of BufferedReader.readline(), which you are using in your code, is not well defined because it is expecting to find an end-of-file condition at the end of the character stream and it won't get that with a MemoryFile until it gets to the end of allocated memory buffer. This explains why you see all the diamond question marks in the logcat output.
To get a better understanding of the end-of-file behavior, you can modify readFile() like this. You will see that 'n' is the length you specify in the MemoryFile constructor.
public void readFile () {
StringBuffer strBuffer = new StringBuffer();
try {
InputStream in = memFile.getInputStream();
int b;
int n = 0;
while ((b = in.read()) != -1) {
n++;
}
Log.d(TAG, String.format("Stream contains %d bytes", n));
/***************
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String inputString;
while ((inputString = reader.readLine()) != null) {
strBuffer.append(inputString + "\n");
}
in.close();
reader.close();
Log.i(TAG, strBuffer.toString());
*******************/
} catch (IOException e) {
e.printStackTrace();
}
}
I can't explain why you see output when the read and write are in the same method, but not when they are in separate methods. Separate methods worked for me (KitKat on Samsung S3). Now that it is understood that BufferReader can't be used on a MemoryFile, the question of why it worked one way and not the other is not significant.
You may find find these MemoryFile test cases helpful as examples of its use. I didn't find any other good examples.
I think the problem is the length of the MemoryFile is not set.
memFile = new MemoryFile("MemoryFileTest", 1000000);
Try memFile = new MemoryFile("MemoryFileTest", LENGTH_OF_YOUR_STRING); Hope it helps.

Get Json with i.e 200 objects, but only 100 displayd on one site

I'm working in my Twitch IRC Bot and we got a Problem.
We receive alot of information through the twitch API (json) like Who followed, dateOf .. viewercounts.. amount of followers and stuff like that.
Were making a Follow-Function to read all the names out of the whole list and set all into our database. First off we tried to just read all and system.output them but we always get the error: org.json.JSONException: JSONArray[100] not found.
We noticed that "0" is holding an array as well so we set the loop to 0-99 and it should change the link then by adding 100+ (next site) and read the JSON again. then it should just continue the loop with the next site.
Below is the Main code as well for the read-methods.
We tried debugging but we wasn't able to find a solution yet x(
MyBot Main Code Snippet:
JSONObject follower = null;
String followername = null;
int listnumber;
offsetvalue = 0;
for(int i = 0; i < TwitchStatus.totalfollows; i++) {
try {
follower = TwitchStatus.followerarray.getJSONObject(i);
} catch (JSONException e2) {
e2.printStackTrace();
}
try {
followername = follower.getJSONObject("user").getString("display_name");
} catch (JSONException e) {
e.printStackTrace();
}
System.out.println("array ist: "+i +" " +followername);
listnumber = offsetvalue+99; // 0+99
if (i == listnumber){
offsetvalue = offsetvalue+100;
try {
TwitchStatus.FollowerTicker();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
// System.out.println("Follower abgleichs-Liste: "+followername);
}
And there is the Reader Method:
////////////////////////////////////////////////////////////////////////////////////
// Twitch Follower Ticker
////////////////////////////////////////////////////////////////////////////////////
private String readAll4(Reader rd) throws IOException {
StringBuilder sb = new StringBuilder();
int cp;
while ((cp = rd.read()) != -1) {
sb.append((char) cp);
}
return sb.toString();
}
public JSONObject readJsonFromUrl4(String url) throws IOException, JSONException {
InputStream is = new URL(url).openStream();
try {
BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
String jsonText = readAll4(rd);
JSONObject json = new JSONObject(jsonText);
return json;
} finally {
is.close();
}
}
public static void FollowerTicker() throws IOException, JSONException {
json = readJsonFromUrl2("https://api.twitch.tv/kraken/channels/dotastarladder_en/follows?direction=DESC&limit=100&offset="+MyBot.offsetvalue+"");
followerarray = json.getJSONArray("follows");
{
JSONObject follower = followerarray.getJSONObject(0);
neuerfollower = follower.getString("created_at");
fname = follower.getJSONObject("user").getString("display_name");
totalfollows = json.getInt("_total");
}
}
Note from the API docs:
limit optional integer Maximum number of objects in array. Default is 25. Maximum is 100.
So, what do you do? Query the next one, of course! Here's the bit of JSON from the linked page, and an example next URL. Basically, you just put an offset in, but the URL already declares it, so...
{
"_total": 1234,
"_links": {
"next": "https://api.twitch.tv/kraken/channels/test_user1/follows?direction=DESC&limit=25&offset=25",
How I would solve this problem is something like this:
Create an AsyncTask that takes in the URL to parse the JSON text.
When the data has been received, start a new task to read the next one.
Read everything received in this JSON string
Compile everything after it has been downloaded as needed.

How to optimize android code

public String getBrotherHood() throws Exception{
client = new DefaultHttpClient();
get = new HttpGet(uri);
res = client.execute(get);
sl = res.getStatusLine();
sCode = sl.getStatusCode();
if(sCode==200)
{
try{
reader = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
readBuffer = new StringBuffer();
while((nl = reader.readLine())!=null){
readBuffer.append(nl);
}
reader.close();
}finally{
if(reader !=null)
{
try{
reader.close();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
return readBuffer.toString();
}
}
I have this code, is this the proper way of writing it, or should i need to follow any coding pattern or standards ??
Please give me some suggestions coz im not to Android Coding.
Update:
public class JSONData {
public ArrayList<String> getBrotherHoodJSON() throws JSONException,IOException,Exception{
ArrayList<String> item = new ArrayList<String>();
JSONArray jA = new JSONArray(getBrotherHood());
for(int i=0; i<jA.length(); i++)
{
JSONObject jO = jA.getJSONObject(i);
String n = jO.getString("name");
item.add(n);
Log.i("JsonData:",jO.getString("name"));
}
return item;
}
public String getBrotherHood() throws Exception{
BufferedReader in = null;
String data= null;
HttpClient client = new DefaultHttpClient();
URI uri = new URI("http://fahidmohammad.in/demo/Android/api.php?user=fah");
HttpGet get = new HttpGet();
get.setURI(uri);
HttpResponse res = client.execute(get);
StatusLine sl = res.getStatusLine();
int sCode = sl.getStatusCode();
if(sCode==200)
{
try{
in = new BufferedReader(new InputStreamReader(res.getEntity().getContent()));
StringBuffer sb = new StringBuffer();
String nl;
while((nl = in.readLine())!=null){
sb.append(nl);
}
in.close();
data = sb.toString();
Log.i("Raw Data:",data);
return data;
}finally{
if(in !=null)
{
try{
in.close();
return data;
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
return data;
}
Here is the updated version the same code.
Taken care of all the mentioned issues.
And also its working like a charm, but don't know the stability of it.
You obviously have declared all variables outside your method even though they seem to be used only within this method. That makes no sense. It prevents several objects from being garbage collected. You better move the declaration into the method.
And the declaration throws Exception doesn't make much sense either. You are better of if you either declare a specific exception that could likely occur or if you convert all unlikely exceptions into RuntimeException so you don't need to declare them.
There is a default code formatter is available eclipse. after wrote your code just type "Control + Shift + F". Your android code will formatting automatically.
one more important point regrading readBuffer varible
At the last of the function you are returning readBuffer.toString() and you initialized this only when status in 200. But if status in not 200 then it would be null (assuming as declaration is not visible ) so null.toString() will thought exception.

java: Do I need to close all the streams?

I have a method that reads text from a file; decompression may be required, depending on an input parameter:
public static String readText(File inFile, boolean compressed) {
InputStream in = null;
InputStreamReader isr = null;
StringBuilder sb = new StringBuilder();//constant resizing is costly, so set the STRING_SIZE
try {
in = new FileInputStream(inFile);
if (compressed) {
in = new GZIPInputStream(in);
}
isr = new InputStreamReader(in);
int length = 0;
char[] cbuf = new char[8 * 1024];
while ((length = isr.read(cbuf)) != -1) {
sb.append(cbuf, 0, length);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
return sb.toString();
}
It was suggested that I use InputStream like this so it is easier to write, and so that in the end I only have to close one thing. I am still a bit worried this might cause a memory leak. So my question is: does anyone knows if the code above is OK? Or do I have to get back to a dozen of streams and close them one by one in a finally block?
Thanks a lot.
Yes, closing the outermost stream/reader is sufficient.
However, your code has another potential bug: new InputStreamReader(in) will use the platform default encoding, which depends on the OS region/language settings. You should specify the encoding of the text file and use it explicitly in the constructor.
Here's one point to add: see if 'in' is null before calling 'in.close()' as the exception could happen without the first assignment succeeding.
Also, it's good form to only catch possible exceptions (e.g. IOException). That way if you add more code and the IDE tells you that a new exception type isn't handled you can add the proper specific code rather than never hearing about it because the catch (Exception ) which was originally for IOException is also (mishandling?) every other type.
Here's the clean Java 7 way which works for anything that implements AutoCloseable/Closeable:
try (InputStream in = compressed ?
new GZIPInputStream(new FileInputStream(inFile))
: new FileInputStream(inFile);
InputStreamReader isr = new InputStreamReader(in))
{
int length = 0;
char[] cbuf = new char[8 * 1024];
while ((length = isr.read(cbuf)) != -1) {
sb.append(cbuf, 0, length);
}
}
catch (Exception e) {
e.printStackTrace();
}
If you're wondering what happens if there's an exception while closing the resource, read about getSuppressedExceptions() which was also added.

Categories