The exception message is printed in an infinite loop - java

I've been writing code that manually prints json (without the json library) after reading a CSV. It's to understand the structure for a project of this scale, which involves IO and Exception handling.
So, I've been debugging this snippet of code since yesterday. I've identified the problem, but have not been able to solve it.
I currently have an infinite loop after the exception message is printed. For context, in the part of the code that is missing, the user inputs the number of files and it creates an array of files. The snippet of code inside my message is a method which verifies if a csv has a an empty field. Count is there to count the line numbers, if count == 1 and there is an empty field, it will throw CSVFileInvalidException, which is a custom exception I made for this project. If count is bigger than 1, it throws CSVDataMissingException, i.e. another custom exception.
The timeline of the debugging goes as follows:
At first, when I had the infinite loop, I thought the regex caused my error, since I heard it could be badly implemented. I checked and each element is exactly what I want (a string, which represents a field in the csv). So, it wasn't regex since the behavior was normal.
Secondly, I realized I accidentally put my try block was inside my while loop, so I put it on the outside. No Luck. The issue still persisted.
Then, I figured out the issue. It read the line handled the exception and since there was no failsafe to exit the while loop, it did so non-stop. So, I added an exit condition for the while loop. So, I added
if ((count > 1) && (s.nextLine() == null || s.nextLine().equals(""))) {
break;
}
This checks if the line number is higher than 1 and if the nextLine is null or empty. I thought this had solved the infinite loop problem that I had. Once I implemented this, nothind after the regex ended up being outputted. I checked with multiple println().
I then realized I made a typo in one of the for loops. Now, I'm back to the same behavior it exhibited earlier. It's redoing the same sequence inside the while loop again. In this case, it's looping the message from CSVFileInvalidException, so i.e. "The file called : " + f[i] + " is invalid. A field is missing. The file is not converted to JSON."
So, I'm assuming there's something that doesn't make sense logically. I've tried multiple solutions and the exceptions are now never reached.
Sorry for the long code, the element that is being repeated is at the bottom, and everything else is inside the while loop, so I'm not sure if it's something I implemented there.
for (int i = 0; i < f.length; i++) {
int count = 1;
try {
while (s.hasNextLine()) {
lines = s.nextLine();
if ((count > 1) && (s.nextLine() == null || s.nextLine().equals(""))) {
break;
}
//isolate the commas, and remove the quotes and extra space, so that the text remains clean and similar
String[] line_parts = lines.replaceAll("^\"", "").split("\"?(,|$)(?=(([^\"]*\"){2})*[^\"]*$) *\"?", -1);
Cloned_Elements[] cloned_elements_array = new Cloned_Elements[line_parts.length];
for (int z = 0; z < cloned_elements_array.length; z++) {
String[] array_ofstring = new String[line_parts.length];
for (int x = 0; x < array_ofstring.length; x++) {
array_ofstring[x] = "lol";
}
cloned_elements_array[z] = new Cloned_Elements(array_ofstring);
}
for (int j = 0; j < line_parts.length - 1; j++) {
if (count == 1) {
if (line_parts[j].equals("") || line_parts[j] == null) {
ce.setCloned_array(line_parts);
throw new CSVFileInvalidException("The file called : " + f[i] + " is invalid. A field is missing. The file is not converted to JSON.");
} else {
if (j < line_parts.length) {
String[] length_1 = cloned_elements_array[j].getCloned_array();
cloned_elements_array[j].setCloned_array(line_parts);
}
}
} else {
if (line_parts[j].equals("") || line_parts[j] == null) {
ce.setCloned_array(line_parts);
throw new CSVDataMissingException("In file " + f[i] + ", there is missing data in line #" + (count) + ". Thus, the file is not converted to JSON.");
} else {
if (j < line_parts.length) {
cloned_elements_array[j].setCloned_array(line_parts);
}
}
}
}
count++;
}
} catch (CSVDataMissingException e2) {
System.err.println(e2.getMessage());
try {
p = new PrintWriter(new FileOutputStream(js[js.length - 1], true));
int line_nb = count+1;
String[] error_array = ce.resize_string_arr();
for (int x = 0; x < error_array.length; x++) {
if (error_array[x].equals("") || error_array[x] == null) {
error_array[x] = "xxx";
}
}
p.println("In file " + f[i] + " ,line " +line_nb + " is missing an element.");
for (int z = 0; z < error_array.length; z++) {
p.print(error_array[z] + " ");
}
p.println();
p.println();
break;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} catch (CSVFileInvalidException e1) {
System.err.println(e1.getMessage());
try {
p = new PrintWriter(new FileOutputStream(js[js.length - 1], true));
p.println("File " + f[i] + " is invalid.");
String[] error_array = ce.resize_string_arr();
for (int x = 0; x < error_array.length; x++) {
if (error_array[x].equals("") || error_array[x] == null) {
error_array[x] = "xxx";
}
}
p.println("Field is missing : " + error_array.length + " detected, 1 is missing.");
for (int z = 0; z < error_array.length; z++) {
p.print(error_array[z] + " ");
}
p.println();
p.println();
break;
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}

Related

Is there a way to make it output the values of result in my code?

I'm working on my university assignment which requires me to program an eviction algorithm. I am new to programming and have only done Python before. Below is what I have done so far. The code compiles fine but I am not getting the output that I was expected to get.
getting user input and then calling the method for no eviction:
System.out.println();
System.out.println("Cache content: ");
print_array(org_cache, size);
System.out.println("Request sequence: ");
print_array(request, count);
try {
copy_array(org_cache, cache, size);
System.out.println("no_evict");
no_evict(cache, size, request, count);
}
catch (Exception e) {
System.out.println("ERROR: no_evict");
the method:
static void no_evict(int[] cache, int c_size, int[] request, int r_size) {
int i = 0;
boolean found = false;
String result = "";
String resultHit = "";
String resultMiss = "";
for(int x = 0; x < r_size; x++) { //for loop goes through every requests
while(i < c_size || found == false) { //while loop brings a page through every cache value
if(request[x] == cache[i]){
found = true;
} else {
i += 1;
}
}
if(found == true) {
result += "h";
resultHit += "h";
} else {
result += "m";
resultMiss += "m";
x += 1; //proceeds to next value in request sequence
}
}
System.out.println(result);
System.out.println(resultHit.length() + "h " + resultMiss.length() + "m");
}
it does not output the result string but instead outputs this:
Cache content:
20 30 10 5 40
Request sequence:
20 30 10
no_evict
You will notice that your program doesn't actually exit. This is because it's stuck in an infinite loop, just as what would happen in Python.
If you run it in a debugger or hit Ctrl-\ in a console, you'll see that it's stuck in this loop:
while(i < c_size || found == false) { //while loop brings a page through every cache value
if(request[x] == cache[i]){
found = true;
} else {
i += 1;
}
}
The condition is true as long as i < c_size because you used ||, logical "or". You probably intended to use &&, so that find = true will break the loop.
PS: The Java compiler doesn't care about indenting, but humans do. Please use your editor's indenting function to make the code easier to read.
As #that other guy mentioned, you are using || instead of &&.
But you don't need the second qualifier. Just use:
i = 0;
while(i < c_size ) {
if(request[x] == cache[i]){
found = true;
break;
} else {
i += 1;
}
}
or
for ( int i=0; i < c_size; i++ ) {
if ( request[x] < cache[i] ) {
found = true;
break;
}
}
There is another problem with your algorithm: you initialise i right at the beginning but never reset it to zero.
You probably want to move the int i = 0 statement between the for and the while statement.

Check or folders recursively, but skip a particular one

Ok, I have a pretty common function to check all files from a path (including sub-folders). In the given path I have multiple folders, like Folder1, Folder2, Folder3... Foldern, and I want to skip Folder2 for example. What is the best method to do that? Down below is my function.
public void loadFileRecursiv(String pathDir)
{
File fisier = new File(pathDir);
File[] listaFisiere = fisier.listFiles();
for(int i = 0; i < listaFisiere.length; i++)
{
if(listaFisiere[i].isDirectory())
{
loadFileRecursiv(pathDir + File.separatorChar + listaFisiere[i].getName());
}
else
{
String cuExtensie = listaFisiere[i].getName();
int pos = cuExtensie.lastIndexOf(".");
String nume = cuExtensie.substring(0, pos);
String acronimBanca = nume.split("_")[0];
String tipAct = nume.split("_")[1];
String dataActString = nume.split("_")[2];
SimpleDateFormat old = new SimpleDateFormat("dd-MM-yyyy");
SimpleDateFormat newPattern = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String dataFormatata = null;
try
{
dataFormatata = newPattern.format(old.parse(dataActString));
}
catch(ParseException e)
{
e.printStackTrace();
}
//String denBanca = inlocuireAcronim(acronimBanca);
processFolder(acronimBanca, acronimBanca);
insertData(listaFisiere[i], nume, acronimBanca, tipAct, dataFormatata);
System.out.println("AICI =========== " + pathDir + File.separatorChar + listaFisiere[i].getName());
moveFile(pathDir + File.separatorChar + listaFisiere[i].getName(), "/u02/ActeConstitutive/Mutate/");
}
}
}
I would advice you to use a Set containing the folders you want to skip.
// get the folders you want to avoid and add them to your set
File Folder2 = new File(pathName);
Set<File> folderToSkip = new HashSet<File>();
folderToSkip.add(Folder2);
// add as many other folders you want to avoid
And then in the for loop, you can check whether or not you want to go inside this folder
for(int i = 0; i < listaFisiere.length; i++){
if(!folderToSkip.contains(listaFisiere[i]){
// do your stuff...
}
}
Whilst your approach is recursive, the recursive part only applies to folder levels. You can skip over a loop operation via the
continue
keyword. Such as below:
for(int i = 0;i<5;i++){
if(i == 0){
continue;
}
System.out.println(i);
}
would skip over 0, the first operation, and output the following
1
2
3
4
Example here
This allows you to build a more modular loop, in my opinion it looks better than
for(int i = 0;i<5;i++){
if(i != 0){
System.out.println(i);
}
}
especially when nesting more conditionals or loops within, like so:
for(int i = 0;i<5;i++){
if(i != 0){
if(i != 0){
if(i != 0){
if(i != 0){
if(i != 0){
// stuff
}
}
}
}
}
}
Do it like this:
for(int i = 0; i < listaFisiere.length; i++)
{
if(listaFisiere[i].isDirectory())
{
if (!listaFisiere[i].getName().equalsIgnoreCase("Folder2"))
loadFileRecursiv(pathDir + File.separatorChar + listaFisiere[i].getName());
}
else
{
add an if statement at the first of method.
public void loadFileRecursiv(String pathDir)
{
if(new File(pathDir).isDirectory() && skip(pathDir))
return;
and make skip method which takes the path and checks that if you want to skip that folder or not; which returns a boolean. true means skip that.

Issues with While loop condition

I am writing a program that reads a text file which contains match results, and then should output them in a table. I have a While loop within a While loop:
Scanner fileread1 = new Scanner(new File("demo.txt"));
int x = 0;
int y = 22;
int i = 0;
while (x <= y) {
while (fileread1.hasNext()) {
fileinput = fileread1.nextLine(); // this reads the next line of
// from the file
String line = fileinput;
String[] split = line.split(":");
boolean result = false;
int homescore1 = 0;
int awayscore1 = 0;
int goalsscored = 0;
boolean att = false;
boolean htt = false;
int atscore = 0;
int htscore = 0;
// When the text line is read, it is then split into four sections.
if (split.length == 4) {
// String text = line.trim();
String userteam = userteaminput;
String hometeam = split[0].trim();
String awayteam = split[1].trim();
String home_score = split[2].trim();
String away_score = split[3].trim();
// this is a test to try convert the goals string into a
// integer. If this fails, the result is not
// not valid and does not get outputted to the console.
try {
homescore1 = Integer.parseInt(home_score);
awayscore1 = Integer.parseInt(away_score);
result = true;
}
catch (NumberFormatException exception) {
// if the try is not able to convert, this will run
errors++;
}
if (userteam.equals(Teams.get(i))) {
if (awayteam.equalsIgnoreCase(userteam)) {
att = true;
games++;
goalsfor = goalsfor + awayscore1;
goalsagainst = goalsagainst + homescore1;
}
if (att == true && awayscore1 > homescore1) {
atwc++;
gameswon++;
}
else if (att == true && awayscore1 < homescore1) {
htwc++;
gameslost++;
}
else if (att == true && awayscore1 == homescore1) {
gamesdrawn++;
}
if (hometeam.equalsIgnoreCase(userteam)) {
htt = true;
totaluser++;
games++;
goalsfor = goalsfor + homescore1;
goalsagainst = goalsagainst + awayscore1;
}
if (htt == true && homescore1 > awayscore1) {
atwc++;
gameswon++;
}
else if (htt == true && homescore1 < awayscore1) {
htwc++;
gameslost++;
}
else if (htt == true && awayscore1 == homescore1) {
gamesdrawn++;
}
}
}
else {
errors++;
}
}
// ********************************************************************
// Leeds IF Statement
// ********************************************************************
if (Rhinos.equals(Teams.get(i)) {
Rhinos.goalsfor = Rhinos.goalsfor + goalsfor;
Rhinos.gameswon = Rhinos.gameswon + gameswon;
Rhinos.gameslost = Rhinos.gameslost + gameslost;
Rhinos.goalsagainst = Rhinos.goalsagainst;
Rhinos.gamesplayed = Rhinos.gamesplayed + games;
}
else if (Bulls.equals(Teams.get(i)) {
Bulls.goalsfor = Bulls.goalsfor + goalsfor;
Bulls.gameswon = Bulls.gameswon + gameswon;
Bulls.gameslost = Bulls.gameslost + gameslost;
Bulls.goalsagainst = Bulls.goalsagainst;
Bulls.gamesplayed = Bulls.gamesplayed + games;
}
x++;
i++;
goalsfor = 0;
gameswon = 0;
gameslost = 0;
gamesagainst = 0;
}
I know that there are only ever going to be 22 teams that have results in the text file supplied, so the first loop should run for 22 times.
The inner loop, will continue whilst the file provided has a next line. The text file may sometimes have more lines of results then other files. Within this loop, I have a reference to an Array item:
if (userteam.equals(Teams.get(i)))
In the first run, this will refer to 0 in my Array which, for the record, is Leeds Rhinos. Once the inner loop has completed, it then moves onto the outer loop - this deals with the results just recorded. If the current team is Leeds Rhinos, it should then add the values. The i should then have 1 added, so for the next loop, it refers to the index of 1 of the array, not 0. (I have more IF statements here, all identical but refer to other teams) Variables get set back to 0, ready for the next run.
The issue I have, is that i does not seem to have 1 added each time it runs through, so I am only getting results passed through for one team. If I manually specify which array index to look (say 3) it will run through, and the team will have their results successfully recorded.
Is there a way I can get 1 added to i every time it loops? I'm not sure if this is the correct java loop to use, but to me, seemed the most logical. There are some objects not declared here - this is just a snippet of the code, left out the declarations as I know they work, and there's a lot declared.
If you're worried about failed incrementation, it would be better to use a For loop.
Instead of having a while (x < y) and sticking an increment statement somewhere in your code,
a
for (i = 0; i < y; i++) { // do tests here }
loop will guarantee that you always increment and run the test for the next team.
For future reference, when using while loops and incrementing, the incrementation is almost always done at the END of the while loop, and not somewhere in between. The incrementation statement should also almost never be in a conditional statement (which might cause an infinite loop).
Your question is not clear. But let's point out something in the code you provided
1) What is the difference between your if and else if statement? They are checking exact same thing
if (userteam.equals(Teams.get(i)) {
Rhinos.goalsfor = Rhinos.goalsfor + goalsfor;
Rhinos.gameswon = Rhinos.gameswon + gameswon;
Rhinos.gameslost = Rhinos.gameslost + gameslost;
Rhinos.goalsagainst = Rhinos.goalsagainst;
Rhinos.gamesplayed = Rhinos.gamesplayed + games;
}
else if (userteam.equals(Teams.get(i)) {
Bulls.goalsfor = Bulls.goalsfor + goalsfor;
Bulls.gameswon = Bulls.gameswon + gameswon;
Bulls.gameslost = Bulls.gameslost + gameslost;
Bulls.goalsagainst = Bulls.goalsagainst;
Bulls.gamesplayed = Bulls.gamesplayed + games;
}
2) What are you doing with variable x, I don't see anywhere you are increasing it.
3) On very first run, when x<=y, the inner loop will finish reading all lines, so even if you increase the X some point, from second run the inner loop will not execute. As it already finished reading all lines. So no point doing this
Again if you provide some more inside on what you want to accomplish, may be with the sample text file data, that would probably help answering your question.
Thank you.
Your formatting is working against you here; properly indented, your code structure is something like this (note, I had to add in missing closing braces, }, at the end of the code you provided as I assume you just missed them when you copied your code over):
Scanner fileread1 = new Scanner(new File("demo.txt"));
int x = 0;
int y = 22;
int i = 0;
while (x <= y) {
while (fileread1.hasNext()) {
fileinput = fileread1.nextLine(); // this reads the next line of
/* stuff */
if (split.length == 4) {
/* stuff */
x++;
i++;
}
}
}
Your incrementation of x and i is nested within if (split.length == 4) {, meaning that x and i will only be incremented in that specific case and not at the end of each iteration of the inner while loop.

if statement constantly printing

My if statement is acting weird, instead of printing only when wrong is greater than 6, it is constantly printing "dead" every time. Any ideas on why that is? I've updated the code so you can better understand my logic.
int j = 0;
String line = "";
for(j = 0; j<64; j++) {
wordLength[j] = wordList[j].length();//gets length of words in wordList
}//end for
int f = 2;//change num to change level
int m = 0;
//creates line first then put into .setText
while(m<wordLength[f]) {
line += "__ ";
m++;
}//end for
jlLines.setText(line);
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {//when enter key pressed
JTextField tf = (JTextField)e.getSource();
letter = tf.getText();
jlLetsUsed.setText(jlLetsUsed.getText() + letter + " ");//sets jlabel text to users entered letter
char[] jlabelText = jlLines.getText().toCharArray();//converts string to character array (array length is length of string)
char userEnteredChar = letter.charAt(0);
int wrong = 0;
int level = 2;//change num to change level
int i = 0;
for(i = 0; i<wordList[level].length(); i++){
if(wordList[level].charAt(i) == userEnteredChar){
jlabelText[3 * i] = ' ';
jlabelText[3 * i + 1] = userEnteredChar;
jlLines.setText(String.valueOf(jlabelText));
}else{
wrong++;
System.out.println(wrong);
}if(wrong >= 6){
System.out.println("dead");
break;
}
}//end for
}//end actionPerformed method
Evidently wrong is always >= 6. One possibility is that level is longer than 1 character and thus the contains check is always false. That's if it's always 'wrong' even with a 'right' guess.
The more likely possibility is that because the check where you increment wrong is inside the loop, any time wordList[level] is 6 or more characters in length and does not contain letter, wrong will be incremented 6 or more times.
You probably should put the check outside the loop.
for(int i = 0; i<wordList[level].length(); i++){
if(wordList[level].charAt(i) == userEnteredChar){
jlabelText[3 * i] = ' ';
jlabelText[3 * i + 1] = userEnteredChar;
jlLines.setText(String.valueOf(jlabelText));
}
}
if(!wordList[level].contains(letter)){
wrong++;
}
if(wrong>=6){
System.out.println("dead");
}
By the way, an obvious suggestion here is that if you are checking contains, you might as well check it first and skip the 'revealing' loop somehow if contains is false.
It looks like wrong should probably be a field somewhere. Shown here I've declared it as a field on the ActionListener. Don't put it on the ActionListener, put it somewhere else, preferably on the containing class. I don't see where else to put it though and this may work initially. The point is to keep track of 'wrong' guesses outside the single guess in actionPerformed. That means you have to declare it somewhere outside the method scope.
tf.addActionListener(new ActionListener() {
int wrong;
#Override
public void actionPerformed(ActionEvent e) {
JTextField tf = (JTextField)e.getSource();
char userEntry = tf.getText().charAt(0);
jlLetsUsed.setText(jlLetsUsed.getText() + userEntry + " ");
int level = 2;
if (!wordList[level].contains(String.valueOf(userEntry))) {
wrong++;
if (wrong >= 6) {
System.out.println("dead");
}
return;
}
char[] jlabelText = jlLines.getText().toCharArray();
for (int i = 0; i < wordList[level].length(); i++) {
if (wordList[level].charAt(i) == userEntry) {
jlabelText[3 * i] = ' ';
jlabelText[3 * i + 1] = userEntry;
}
}
jlLines.setText(String.valueOf(jlabelText));
}
});

Entering an If statement with a hashmap conditions

for (int i = 0; i < pac.length; i++)
{
for (int j=0;j<mem.length;j++)
{
String[] words = mem[j].split(" ");
for (int k = 1; k < words.length; k++)
{
if (words[k].equals(pac[i])
{ //done system.out.println here and it's right
if (!members.containsKey(pac[i])) //won't enter this if correctly
{
members.put(pac[i], " " + words[0]);
}
else
{
String old = members.get(pac[i]);
members.put(pac[i], old + " " + words[0]);
}
}
else
{
members.put(pac[i], "");
}
}
}
}
I need the code to take an array pac which contains a list of organizations and then a list of people's names with their organizations after. I have to put them into a hashmap of members. I cant seem to get it to enter the if statement correctly though. It reaches there correctly. I've used the printing to see what should go into it and that part is correct. Members is an empty hashmap yet all but only one iteration of the loops will go into the first if statement when most should go into it.
use label you can solve your problem. because any one iteration of 2nd loop can empty your member. try this
for (int i = 0; i < pac.length; i++) {
action:
for (int j = 0; j < mem.length; j++) {
String[] words = mem[j].split(" ");
for (int k = 1; k < words.length; k++) {
//System.out.println(words[0] + "ttt");
if (words[k].equals(pac[i])) {
System.out.println(words[k]);
if (!members.containsKey(pac[i]))
{
members.put(pac[i], " " + words[0]);
break action;
} else {
String old = members.get(pac[i]);
members.put(pac[i], old + " " + words[0]);
break action;
}
} else {
members.put(pac[i], "");
}
}
}
}
and use persons as a key for members instead of organization. because a org have more number of persons.

Categories