I'm writing a little program to analyze some data I have and this code, which worked yesterday, is no longer working.
For the life of me, I can't tell why. To my eye, everything is as it should be. I've tried re-syncing the folder on my computer with my GitHub Repo and still was receiving the same error. Maybe a second pair of eyes could help me out?
The text file being read from can be found here.
Here are the methods referred to by the stack trace:
public static void main(String[] args) throws IOException{
FileManagementMethods fmm = new FileManagementMethods();
fmm.runProgram();
}
void runProgram() throws IOException{
boolean doesFileExist = doesFileExist();
if(doesFileExist){
int numLines = getNumberOfLines();
String[] linesFromFile = getLines(numLines);
WeatherAnalysisMethods wam = new WeatherAnalysisMethods();
wam.parseFileAverageTemp(linesFromFile);
wam.parseFileAverageHumidity(linesFromFile);
wam.predictNextTemperature(linesFromFile);
} else{
try {
throw new IOException("Could not find log.txt in default directory");
} catch (IOException e) {
e.printStackTrace();
}
}
}
void parseFileAverageHumidity(String[] linesFromFile) throws IOException{
int[] humiditiesFromFile = new int[linesFromFile.length];
humiditiesFromFile = getHumiditiesFromFile(linesFromFile.length);
int averageFromFile = 0;
for(int i = 0; i < humiditiesFromFile.length; i++){
averageFromFile += humiditiesFromFile[i];
}
averageFromFile = averageFromFile / humiditiesFromFile.length;
String outString = "Average humidity for whole file = " + averageFromFile;
FileManagementMethods fmm = new FileManagementMethods();
fmm.saveAnalyzedData(outString);
}
int[] getHumiditiesFromFile(int numLines){
int[] humiditiesFromFile = new int[numLines];
FileManagementMethods fmm = new FileManagementMethods();
String[] lines = fmm.getLines(numLines);
int i = 0;
while(1 < numLines){
String[] lineDivides = lines[i].split(",");
String tempString = lineDivides[4];
humiditiesFromFile[i] = Integer.parseInt(tempString);
i++;
}
return humiditiesFromFile;
}
Line 51:
String tempString = lineDivides[4];
And here is the stack trace:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 4
at org.weatheralert.analysis.WeatherAnalysisMethods.getHumiditiesFromFile(WeatherAnalysisMethods.java:51)
at org.weatheralert.analysis.WeatherAnalysisMethods.parseFileAverageHumidity(WeatherAnalysisMethods.java:22)
at org.weatheralert.analysis.FileManagementMethods.runProgram(FileManagementMethods.java:22)
at org.weatheralert.analysis.Main.main(Main.java:9)
If you guys need more information, don't hesitate to ask.
The problem is here, inside your getHumiditiesFromFile method:
while(1 < numLines){
It should be
while (i < numLines){
Since inside this loop you're calling humiditiesFromFile[i].
As Foo Bar User noted in comment, the error may be here:
String tempString = lineDivides[4];
It would be better to make sure there are at least 4 items in that array.
Besides that, the error noted in the section above (assuming it's not a typo) could also throw this Exception for being in an infinite loop.
You've hardcoded a 4 here without checking to see if it exists:
String tempString = lineDivides[4];
You will need to do some data validation beforehand. You're assuming that the line you read has at least three commas. Either change the code to check, or validate the file.
So, it was a silly issue.... JSoup had a couple bad connections and didn't save some of the data I needed it to save. So it didn't recognize some of the lines of data.
Once I fixed the actual data, it runs without issue again.
I apologize for wasting your time.
Related
Now this may sound like a question that has been repeated many times before but I've done a day of research with people that has other reasons for this Issue.
I have a function that reads a part of the save file and its been shown that it does receive the correct data. So the error is that the integer variable completely ignores the new variable and shows no change in the live debugger so like many other post it is not just a duplicate object error. I cant seem to pinpoint what is the main issue is here and it's the last major thing holding me back. Any help would be great and I'm very extremely sorry if I did manage to miss a topic about this on the internet.
Code that fails:
#Override
public void read(List<String> data) {
//world positions are not being changed at all
System.out.println(data.get(1));
int test = Integer.valueOf(data.get(1).replaceAll("[^\\d.]", ""));
worldXPos = Integer.valueOf(data.get(0).replaceAll("[^\\d.]", ""));
worldZPos = test;
}
Another class that gives the data:
public void readSaveFunctions(){
if(!gameSaves.exists()){
gameSaves.mkdir();
}
String currentLine;
try {
List<String> data = new ArrayList<String>();
FileReader read = new FileReader(currentFile);
BufferedReader reader = new BufferedReader(read);
String key = "";
while((currentLine = reader.readLine()) != null){
if(currentLine.contains("#")){
key = currentLine;
data = new ArrayList<String>();
}else if(currentLine.contains("*end")){
for(int i = 0; i < saves.length; i++){
String tryKey = "#" + saves[i].IDName();
if(tryKey.equals(key)){
key = "";
saves[i].read(data);
}
}
}else data.add(currentLine);
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Another way of explaining it is this:
Debugger is set to step - to - step mode so I see each line getting executed at human speed then I get to a line like this but all of the ones setting the variables have the same effect:
worldXPos = Integer.valueOf(data.get(0).replaceAll("[^\\d.]", ""));
and the debugger shows the two integers having different numbers but the instant class variable stays exactly the same with no effect in the debugger after the line goes through.
Update:
I forgot to mention the method has a #override method and it seems that this #override may be causing this issue, now finally I may have a path to follow again
So I found my answer: The AWT thread manage to activate calling a method from another class that changed the integer before it could be read. It really though me off at first because the debugger only showed one of the threads and with no way to know the other one was actively changing it to early. Thanks for all the help :P.
So I've got a program that generates large binary sequences, and if the string length goes above 4094 it doesn't print. Here's a code snippet the highlights the problem:
private static void ALStringTest() {
String al = "1";
for (int i = 0; i < 5000; i++) {
al += "1";
System.out.println(al.length());
System.out.println(al);
System.out.println(al.isEmpty());
}
}
What's interesting is the length continues to increase, and the boolean value stays false, but I'm unable to see the strings of length 4095 and above.
It's also not a printing error, as I've attempted to write the strings to xml and they don't appear either, all I get is spaces equal to the strings length.
Edit:
I've tried printing a file using this snippet and I have the same problem:
private static void ALStringTest() throws IOException {
File fout = new File("out.txt");
FileOutputStream fos = new FileOutputStream(fout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
String al = "1";
for (int i = 0; i < 5000; i++) {
al += "1";
bw.write(al);
bw.newLine();
System.out.println(al.length());
System.out.println(al);
System.out.println(al.isEmpty());
}
bw.close();
}
However, people have confirmed this works on external machines (thanks) (as well as on my own using javac, I'm lead to believe this may be Eclipse specific.
Anyone know why Eclipse might be doing this?
the boolean will stay false as hashcode of al is some value and that of "" is 0, == checks for reference.
So it turns out it was an IDE issue:
Simply copying it to a text editor revealed the strings. I'll update when I find the offending option.
The possible reason of this maybe the defect of console which is rapidly printing output results. So that maybe it's only happening in console output. I've tested those each and the result was sometime it prints false only more than 6 times or sometime it prints only length That shouldn't be happened as scenario. But everything works fine when we use thread and make it sleep even 1 millisecond. The output is fine enough as codes,
class ThreadTest extends Thread {
public ThreadTest() {
super();
}
public void run() {
String al = "1";
for (int i = 0; i < 5000; i++) {
try {
sleep(1);
al += "1";
System.out.println(al.length());
System.out.println(al);
System.out.println(al.equals(""));
} catch (InterruptedException e) {
}
}
}
}
Call this in main method
new ThreadTest().start();
(For this I need to use Arrays - not Array lists. Snipping code to make it easier to follow. Renaming variables and constants to label so others who read this later understand what I am doing better.)
At the class level I have my arrays defined like so:
private static final int CONSTANT = 20;
public static String[] arrayName = new String[CONSTANT - 1];
and in the main method I am pointing to the method like so:
readArrays("filenName.txt", arrayName);
and a line like that points to the following complete method which is where the error occurs:
public static void readArrays(String codeFile,
String[] Arrays)
{
try ( Scanner fin = new Scanner ( new File(codeFile) ); )
{
for (int i = 0; i < CONSTANT - 1; i++)
{
Arrays[i] = fin.next();
}
}
catch (FileNotFoundException e)
{
System.err.println( "Read Error: " + e.getMessage() );
}
It shows no errors in NetBeans, but in the console window the exact error message is:
run:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1371)
at mp06.Main.readArrays(Main.java:47)
at mp06.Main.main(Main.java:33)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)
What is causing this error? Ultimately, my goal is to write the entire contents of multiple text files to multiple arrays using the same method and without using any other approach.
try ( Scanner fin = new Scanner ( new File(codeFile) ); )
{
for (int i = 0; i < CONSTANT - 1 && fin.hasNext(); i++)
{
Arrays[i] = fin.next();
}
}
catch (FileNotFoundException e)
{
System.err.println( "Read Error: " + e.getMessage() );
}
You also need to check Scanner has next.
In Java8, you can use stream to read file:
List<String> contents = Files.lines(Paths.get("filenName.txt")).collect(Collectors.toList());
The below code might help you.
There are couple of things, you have to check whether next element is exists in scanner before you call next() and the other one is the constant "20", it will end up with Array Index Bounds exception if the size exceeds 20.
Adding them in the list and converting them to an array will resolve this. Try the below code.
List<String> list = new ArrayList<String>();
while (fin.hasNext()) {
list.add(fin.next());
}
String[] array = new String[list.size()];
list.toArray(array);
for (String str: array) {
System.out.println(str);
}
I've got some Java code that runs quite the expected way, but it's taking some amount of time -some seconds- even if the job is just looping through an array.
The input file is a Fasta file as shown in the image below. The file I'm using is 2.9Mo, and there are some other Fasta file that can take up to 20Mo.
And in the code im trying to loop through it by bunches of threes, e.g: AGC TTT TCA ... etc The code has no functional sens for now but what I want is to append each Amino Acid to it's equivalent bunch of Bases. Example :
AGC - Ser / CUG Leu / ... etc
So what's wrong with the code ? and Is there any way to do it better ? Any optimization ? Looping through the whole String is taking some time, maybe just seconds, but need to find a better way to do it.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class fasta {
public static void main(String[] args) throws IOException {
File fastaFile;
FileReader fastaReader;
BufferedReader fastaBuffer = null;
StringBuilder fastaString = new StringBuilder();
try {
fastaFile = new File("res/NC_017108.fna");
fastaReader = new FileReader(fastaFile);
fastaBuffer = new BufferedReader(fastaReader);
String fastaDescription = fastaBuffer.readLine();
String line = fastaBuffer.readLine();
while (line != null) {
fastaString.append(line);
line = fastaBuffer.readLine();
}
System.out.println(fastaDescription);
System.out.println();
String currentFastaAcid;
for (int i = 0; i < fastaString.length(); i+=3) {
currentFastaAcid = fastaString.toString().substring(i, i + 3);
System.out.println(currentFastaAcid);
}
} catch (NullPointerException e) {
System.out.println(e.getMessage());
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
fastaBuffer.close();
}
}
}
currentFastaAcid = fastaString.toString().substring(i, i + 3);
Please replace with
currentFastaAcid = fastaString.substring(i, i + 3);
toString method of StringBuilder create new instance of String object every time you call it. It still contain a copy of all your large string. If you call substring directly from StringBuilder it will return a small copy of substring.
Also remove System.out.println if you don't really need it.
The big factor here is you are doing the call to substring over a new String each time.
Instead, use substring directly over the stringbuilder
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
System.out.println(currentFastaAcid);
}
Also, instead of print the currentFastaAcid each time, save it into a list and print this list at the end
List<String> acids = new LinkedList<String>();
for (int i = 0; i < fastaString.length(); i+=3){
currentFastaAcid = fastaString.substring(i, i + 3);
acids.add(currentFastaAcid);
}
System.out.println(acids.toString());
Your main problem besides the debug output surely is, that you are creating a new String with your completely read data from the file in each iteration of your loop:
currentFastaAcid = fastaString.toString().substring(i, i + 3);
fastaString.toString() will give the same result in each iteration and therefore is redundant. Get it outside the loop and you will surely save some seconds runtime.
Apart from suggested optimization in the serial code, I will go for parallel processing to reduce time further. If you have really big file, you can divide the work of reading file and processing read-lines, in separate threads. That way, when one thread is busy reading nextline from large file, other thread can process read-lines and print them on console.
If you remove the
System.out.println(currentFastaAcid);
line in the for loop, you will gain quite decent time.
I have written a program to monitor the status of some hard drives attached to a RAID on Linux. Through this program I execute several command line commands. An interesting error occurs though....the program runs for a good three minutes before it seems that it can no longer correctly execute the command it had been previously executing (for many iterations).
It spits out an array index error (my variable driveLetters[d]) because it appears to miss the drive somehow (even though it found it hundreds of times before).
Other things to note...if I tell it to reset int "d" to "0" if it exceeds the number of drives...the program won't crash and instead will just become stuck in an infinite loop.
Also, the time at which the program crashes varies. It doesn't appear to crash after a set number of intervals. Finally, I don't get any kind of memory leak errors.
Here is some of code that should reveal the error:
public static void scsi_generic() throws IOException, InterruptedException
{
int i =0;
int d =0;
int numberOfDrives = 8;
char driveLetters[] = {'b','c','d','e','f','g','h','i','j','k','l','m'};
String drive = "";
while (i <= numberOfDrives)
{
System.out.println("position 1");
List<String> commands = new ArrayList<String>();
commands.add("cat");
commands.add("/sys/class/scsi_generic/sg"+i+"/device/sas_address");
SystemCommandExecutor commandExecutor = new SystemCommandExecutor(commands);
int driveFound = commandExecutor.executeCommand();
if (driveFound == 0)
{
System.out.println("Folder: sg" + i + " was found." );
StringBuilder stdout = commandExecutor.getStandardOutputFromCommand();
String data = stdout.toString();
String sas = data.substring(11,12);
int sasA = Integer.parseInt(sas,16);
boolean matchedSG = false;
while (matchedSG == false)
{
System.out.println("position2");
List<String> lookSD = new ArrayList<String>();
lookSD.add("test");
lookSD.add("-d");
lookSD.add("/sys/class/scsi_generic/sg"+i+"/device/block:sd" + driveLetters[d]);
SystemCommandExecutor commandSearch = new SystemCommandExecutor(lookSD);
int sdFound = commandSearch.executeCommand();
StringBuilder stdout3 = commandSearch.getStandardOutputFromCommand();
StringBuilder stderr = commandSearch.getStandardErrorFromCommand();
String sdFound2 = stdout3.toString();
if (sdFound == 0)
{
matchedSG = true;
System.out.println("Found the SD drive.");
drive = "sd"+driveLetters[d];
System.out.println(sasA);
hdsas.set(sasA , sas);
d = 0;
i++;
loadDrives(drive , sasA);
}
/* else if (sdFound != )
{
System.out.println("Error:" + sdFound);
System.out.println(d+ " "+ i);
}
*/
else if ( d >= 8)
{
System.out.println("Drive letter: " + driveLetters[d]);
System.out.println("Int: " + i);
// System.out.println(sdFound2);
System.out.println("sd error: "+ sdFound);
// System.out.println(stderr);
//System.out.println(sdFound2 + " m");
}
else
{
d++;
}
}
}
else
{
System.out.println("Folder: sg" + i + " could not be found.");
i++;
}
d =0;
}
}
Any help or suggestions would be awesome! Thanks.
EDIT:
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.
This is no direct answer to your question, but it still might help you:
I often have to find bugs in code like yours (very long methods with "global" variables, that is, variables declared at the beginning of a method and used all over then). Just by refactoring the code properly (short methods with a single purpose each), the cause of the bug becomes immediately visible to me and is fixed within a second (while the refactoring itself takes much longer).
I guess that's what everyone trying to offer you help is doing anyway: Refactor your code (probably only in one's head) so that is (much) more easy to understand what's going on.
The solution I found was to use the java library for testing if a directory exists rather than doing it through the linux command line.
Ex:
File location = new File("directory");
if (location.exists())
{
}
No idea why it works and doesn't crash, where as the linux command line did after a short period of time, but it does.