I'm looping through a text file using both a while and for loop.
The goal of my code is to iterate through my CSV comma-delimited text file with 2 columns and only parse through strings to a map. I don't want integers, and that's what my program is meant to do.
The problem is, every time I restart the while loop to go to the next line, it restarts my variables and assumes it's always on the first line.
Here's my code:
CSVReader reader = new CSVReader(new FileReader("sortMark12.txt"), ',');
List<String[]> myEntries = reader.readAll();
reader.close();
//mark12Line is a string of the file name, and mark12Br is a buffered reader
//While the text file's line is not empty
whileloop: while ((mark12Line = mark12Br.readLine()) != null)
{
//Declaring row, this keeps getting reset
for (int row = 0; row < myEntries.size(); row++)
{
//Declaring column, this also keeps getting reset
for (int column = 0; row < myEntries.get(row).length; column++)
{
//While the row and column is not an integer
while (!isInteger(myEntries.get(row)[column]))
{
//Put the value in position row and column into the map.
mark12Map.put(mark12Line.split(",")[0], myEntries.get(row)[column]);
continue whileloop;
}
}
}
}
What's happening in my code is that on the first row and first column, it detects it as an integer, so it does not put that integer into the map. The first row and second column is a string, so that is put inside the map.
The problem is, once that is done, it continues my while loop, and both row
and column
have been reset to 0. So it acts as if it's still on the same line, even though I have delcared it to increment at row++
and column++
.
Why do my integer variables keep getting reset to 0? I need them to increment everytime for a different line.
Am I declaring them wrong, or is something else breaking my code.
If you need any more code, then please let me know.
Thank you for your help.
From what I understand from your problem description and your response to Paul Guiheen's answer, I think the following code may be closer to your application's intended logic:
/* EDITED ...see below */
The row
and column
variables are being reset every time the outer while
loop executes because they are being initialized inside the while
loop. In other words, they will be re-initialized to zero every time the outer while
loop executes.
You could move their initialize outside the outer while
loop to avoid this, like so:
int row = 0;
int column = 0;
whileloop: while (/* test something */)
{
for ( ; row < myEntries.size(); ++row)
{
for ( ; row < myEntries.get(row)[column]; ++column)
{
/* do stuff */;
}
}
}
This will fix the problem you asked about, and in some cases it may be justified. But in your case, it happens to create a second problem (see next paragraph). So I would say that there is a better way (see "Solution" section below).
The reason this won't work in your case is because you are using a continue <label>
statement. The problem is that it will entirely skip and thus prevent the update statement of each for
loop from executing. Unless you have a very good reason to use a continue <label>
or break <label>
statement, then don't. Jumping around your code like this can cause all sorts of hard-to-diagnose problems. And it's usually a sign of a fundamental design error anyway.
If you think you have to use a continue <label>
or break <label>
statement, then you probably need to refactor (i.e. re-structure your code so that you don't need to use it in the first place).
Basically, what you want to do is some variation of the following in order to iterate through every row, and within every row to iterate through every column:
for (int row = 0; row < myEntries.size(); ++row)
{
for (int column = 0; column < myEntries.get(row).length; ++column)
{
/* do stuff */;
}
}
Where your "stuff" is this:
if (!isInteger(myEntries.get(row)[column]))
{
mark12Map.put(mark12Line.split(",")[0], myEntries.get(row)[column]);
}
But the confusing part is that you also have to read and validate a line every row:
if ((mark12Line = mark12Br.readline()) != null)
{
/* process each column in the row */;
}
So where do you put it? Just inside the "row" for
loop (so that you read one line for each row) and just outside the "column" for
loop (because there are multiple columns in every one line):
for (int row = 0; row < myEntries.size(); ++row)
{
if ((mark12Line = mark12Br.readline()) != null)
{
for (int column = 0; column < myEntries.get(row).length; ++column)
{
/* do stuff */;
}
}
}
This will get the job done, but it will take longer than needed. We can optimize this if we notice that whenever there are no more lines to read, then we are done even if we have not reached the maximum number of rows yet. So we add the following else
block to the if
that reads in a line:
else
{
break; // break out of outer loop because there are no more lines to read
}
Putting together all of the above, the final product looks like this:
for (int row = 0; row < myEntries.size(); ++row)
{
if ((mark12Line = mark12Br.readline()) != null)
{
for (int column = 0; column < myEntries.get(row).length; ++column)
{
if (!isInteger(myEntries.get(row)[column]))
{
mark12Map.put(mark12Line.split(",")[0], myEntries.get(row)[column]);
}
}
}
else
{
break;
}
}