StringTokenizer NoSuchElements - java

I have created a method that reads a file set like this (//... are comments, ignore them):
5 // n jobs
2 // n tools
1 4 5 6 2
1 5 4 2 3
The matrix represents the tools used for each job but it doesn't really matter here.
Here is the method :
public static JobS inputJobMatrix(){
String line = ""; // Line in tokenizer
int jobN = inputJobN(); //First number of the file (jobs) works
int toolN = inputToolN(); //Second number of the file (tools) works
//Instancing JobS object
JobS inputJobS = new JobS(jobN, toolN);
int[][] tabFill = new int[jobN][toolN];
int[] tabFillOrder = new int[jobN];
try {
// Initializing reader.
FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr);
StringTokenizer st = new StringTokenizer(line);
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
//Instancing tab for Job Order 1...n
int[] a = new int[jobN];
for (int i=0; i<jobN; i++){
a[i]=i+1;
}
//Filling Order tab with Job order
JobS.fillLine(tabFillOrder, a, 0); //Fills the tab with the tab a (make a copy of it we could say)
//Reading the matrix line by line and filling tab line
for(int i=0; i<jobN; i++){
for(int j=0; j<toolN; j++){
String str = st.nextToken();
System.out.println(str);
tabFill[i][j] = Integer.parseInt(str);
}
line = br.readLine();
}
inputJobS.setJobS(tabFill);
br.close();
} catch (IOException e) {
System.out.println("File not found exception in inputJobMatrix.");
}
return inputJobS;
}
Which results in :
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at pProgra.ReadJobS.inputJobMatrix(ReadJobS.java:84)
at pProgra.PPMain.main(PPMain.java:14)
I've tried looking for problems in my loops but didnt find any, and i can't understand why it doesn't work.
The goal here is to fill a bidimensionnal int array with the matrix of the input file (for exemple the one i've given previously with jobs and tools) and use that array for my object (JobS, i'll give the constructor here too if it can help) :
public class JobS {
private int[] jobOrder;
private int[][] jobS;
public JobS(int jobs, int tools){// Creates one more line for the title (jobOrder).
super();
int[][] tab = new int[jobs][tools];
int[] tab2 = new int[jobs];
this.jobS = tab;
this.jobOrder = tab2;
}
And the setter i use at the end:
public void setJobS(int[][] jobS) {
this.jobS = jobS;
}
I tried detailing the code as much as possible with comments, I hope you will understand what i want to do.
This is the first time i'm trying to do a "complex" application so maybe i'm just stupid and forgot something, but right now i've been searching for an hour and still have no clue what is causing this ..
Hope you can help, thanks in advance !
L.L.

as you can see the String line is empty:
String line = ""; // Line in tokenizer
so here st is empty:
StringTokenizer st = new StringTokenizer(line);
hence when you call this:
String str = st.nextToken();
an exception occurs.
ensure that the line has some data first, by instantiating the StringTokenizer after the for loop.
Example
change this:
StringTokenizer st = new StringTokenizer(line);
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
to this:
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
StringTokenizer st = new StringTokenizer(line);
side note - this code:
line = br.readLine();
will overwrite the value of line at each iteration within the loop, that could be what you wanted but if you want to append all the lines of text the readLine() gets then you can do this:
line += br.readLine();

Related

Filling a double[][] from the CSV file

I have this CSV file:
World Development Indicators
Number of countries,4
Country Name,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014
Bangladesh,6.28776238,13.20573922,23.46762823,30.16828408,34.35334451,44.94535882,55.19256723,62.82023906,74.42964608,80.03535051
"Bahamas, The",69.21279415,75.37855087,109.340767,102.7875065,101.2186453,118.8292307,81.5628489,80.65383375,76.05187427,82.29635806
Brazil,46.31418452,53.11025849,63.67475185,78.5549801,87.54187651,100.8810115,119.0023853,125.0018521,135.3050481,138.9514906
Germany,94.55486999,102.2828888,115.1403608,126.5575074,126.2280577,106.4836959,109.6595675,111.5940398,120.9211651,120.4201855
I am trying to store countries' data(double once) into a matrix(double[][]). Here is the code that I have so far:
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
String row;
int indexRow = 0;
int indexColumn = 0;
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine();
br.readLine();
String line = br.readLine();
while(line != null && !line.isEmpty()){
line = br.readLine();
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
for(int i = 1; i < array.length; i++){
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
}
System.out.print(Arrays.deepToString(table));
return table;
}
I am getting an arror : NullPointerException at:
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
I cant figure out why. I tried different combinations. nothing seems to work. It seems to pick up the numbers from the CSV file and store them, but when I call:
System.out.print(Arrays.deepToString(table));
it does not print out anything, hence I cant check if its stored properly or not. Could you tell me: 1. Why I am getting an error. 2. Why System.out.println does not print out an array. Thanks
If we assume that name of a country will not contain a digit and country name and numbers will be only comma separated, then following can be done without regex. I have changed file reading a little bit because it can run into issues.
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
int indexRow = 0;
int indexColumn = 0;
BufferedReader br = new BufferedReader(new FileReader(fileName));
br.readLine(); // ignore first line
br.readLine(); // ignore second line
br.readLine(); // ignore third line (contains title)
String line;
while (true) {
line = br.readLine();
if (line == null) break; // end of file reading
int index = 0;
while (true) {
index = line.indexOf(",", index) + 1;
if (Character.isDigit(line.charAt(index))) {
break;
}
}
// from index, line is expected to contain comma separated numbers
String[] array = line.substring(index).split(",");
for (int i = 0; i < array.length; i++) {
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
}
System.out.print(Arrays.deepToString(table));
return table;
}
In the csv, first 3 lines are not real country's data. So read in line-4 before while loop starts.
In while loop, first finish the processing of line string first. Eg: regular expression check & assign split data into table.
Then only read in next line at end of while loop, to be processed in next iteration.
Feel free to try this out:
public double[][] getParsedTable() throws IOException {
double[][] table = new double[4][10];
int indexRow = 0;
int indexColumn = 0;
// check whether you need to handle any exception for this
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = null;
try {
// line 1-3 are not real country's data
br.readLine();
br.readLine();
br.readLine();
// first country data begin at line 4
line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
while (line != null && !line.isEmpty()) {
String[] array = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1);
for (int i = 1; i < array.length; i++) {
table[indexRow][indexColumn] = Double.parseDouble(array[i]);
indexColumn++;
}
indexColumn = 0;
indexRow++;
// read next line only at end of loop, not beginning of loop
// line is ready to be processed at next iteration
try {
line = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.print(Arrays.deepToString(table));
return table;
}
Arrays.deepToString is wrong. You are passing in an array of primitives. When you pass it in, you pass in double[][]. This is interpeted as Object[] where the objects are double[], so it will try to print double[] objects, and not print doubles.
One solution is to create an array Double[][].
Change
double[][] table = new double[4][10];
to
Double[][] table = new Double[4][10];
Autoboxing will convert each double to a Double. Since Double is an object and not a primitive, deepToString will print out each Double individually. If you read the javadoc for deepToString it explains that it operates recursively on arrays of reference type, not on primitive arrays.
If you want to stick with double[][]
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < table[i].length; j++) {
System.out.print(table[i][j]);
System.out.print(' ');
}
System.out.println();
}

Reading a text file into a 2D array

I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();

create new array from old array column

I'm new to OOP, but I'm trying to create my first bigger program.
I've read a txt-file and stored the values (doubles) into an array, I call it originalArray. The text has two columns and 20 lines. So when I want to print the values in the first column of the txt-file I simply write:
System.out.println(originalArray[0]);
OUTPUT: 1991.00
300.50
498.50 .... et cetera...
My problem is that i'd like to use a for-loop (or whatever) to create two new arrays, each consisting one column from the "original array".
I thought it would be as simple as using a for-loop, like this;
double [] newArray = new double [20];
for(int i = 0; i < originalArray.length; i++){
newArray[i] = originalArray[0] //if I want to fill it with the first
//columns data... the second would be newArray2[i] = originalArray[1]
}
But this fills the new array with ONE element from the column in the originalArray... So - I need help to figure of how to write the loop to fill the new arrays with all elements from one chosen column.
Very grateful for help!
Regards/ frustrated newbie
EDIT: This is how I read the txt file:
String file = "C:\\Users\\komena\\Desktop\\30th-sales.csv";
BufferedReader br = null;
String line = "";
String splitBy = ";";
originalArray = new double [20];
br = new BufferedReader(new FileReader(file));
br.readLine();//skip the first line to get rid of header…
while ((line = br.readLine()) != null) {
String[] readlineArray = line.split(splitBy);
for (int i = 0; i < readlineArray.length; i++) {
originalArray[i] = Double.parseDouble(readlineArray[i]);
}
Whole text (csv) file:
300.50;330.00
489.50;296.50
34.50;399.50
900.00;1890.00
2052.00;568.00
354.00;0.00
399.00;0.00
1299.50;0.00
426.00;259.00
29.50;2300.50
99.50;349.50
2500.50;0.00
358.50;113.00
789.00;239.50
998.00;348.00
16.50;679.00
800.00;723.00
1899.50;950.50
550.50;568.00
Create the new 2D array with the size of the 1st dimension the same as the originalArray's length and the 2nd dimension the size of 2 (2 columns). Then simply loop it and add the old values to one column and also the new ones if reuqired, otherwise they will be set as 0.0 defaultly.
double originalArray[] = {1991.00, 300.50, 498.50};
double newArray[][] = new double[originalArray.length][2];
for (int i=0; i<originalArray.length; i++) {
newArray[i][0] = i // Fill the 1st column with sth like ID
newArray[i][1] = originalArray[i]; // Copy the 1D array to the 2nd column
}
System.out.println(Arrays.deepToString(newArray)); // Print all the array values
Output:
[[1.0, 1991.00],
[2.0, 300.50],
[3.0, 498.50]]
Moreover you read the file wrong. Notice that you have 2 values in the each line separated with ; and lines separated with \n. So read the line by line and add 2 values to the array.
The i variable represents the actual index of the originalArray[].
BufferedReader br = null;
String line = "";
int i=0;
double originalArray[] = new double[20];
br = new BufferedReader(new FileReader(file));
br.readLine();//skip the first line to get rid of header…
while ((line = br.readLine()) != null && i<originalArray.length) {
String[] readlineArray = line.split(";");
originalArray[i] = Double.parseDouble(readlineArray[0]);
originalArray[i+1] = Double.parseDouble(readlineArray[1]);
i+=2;
}
System.out.println(Arrays.toString(originalArray));

How do I separate these tokens and skip the lines when I need to?

//I am trying to take in this file and separate the Cards based on the ######### at the end //I am making a robocop style card game in java for fun and I made the cards in plain text file and I want to be able to read in the file and separate the file into cards. Ultimately I want to be able to call these cards and print them out when needed.
try{
File file = new File("MyText.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while((line = reader.readLine()) != null){
addCard(line);
}
}catch(Exception ex){
ex.printStackTrace();
}
//Problem! This only prints the first card?!? HELP!
for(i = 0; i < playerList.size(); i++){
System.out.println(playerList.get(i));
}
}
void addCard(String lineToParse){
String[] tokens = lineToParse.split("##########");
// How do I increment the token to the next token and add to playerList?
playerList.add(tokens[0]);
}
}
For your addCard method, you need:
void addCard(String lineToParse){
String[] tokens = lineToParse.split("##########");
for(int i=0; i<tokens.length; i++) {
playerList.add(tokens[i]);
}
}

Random line select from a file

I'm trying to make a method that a random line from lol.txt (which has 113 lines) would be chosen and sent out as message box. How it should work:
Generates random number from 0 till 112
a for loop should go over the random number of lines
output the randomly generated line as a message box
In my case step 2 doesn't work so I was hoping that someone could suggest on that. Here's the code:
public void close(){
try{
Random random = new Random();
int randomInt = random.nextInt(112);
FileReader fr = new FileReader("lol.txt");
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
Scanner scan = null;
for (int i = 0; i < randomInt + 1; i++) {
scan = new Scanner(line);
line = scan.nextLine();
}
JOptionPane.showMessageDialog(null,line);
}catch (IOException e){
JOptionPane.showMessageDialog(null,e.getMessage()+" for lol.txt","File Error",JOptionPane.ERROR_MESSAGE);
}
}
If you want to send me the solution with an array list that's fine but I would really like it to be how I planned it initially.
It's best to use a list for this purpose, as well as make the random size dynamic to adjust to the size of your file. In case you wanted to add more lines without having to change code.
BufferedReader reader = new BufferedReader(new FileReader("lol.txt"));
String line = reader.readLine();
List<String> lines = new ArrayList<String>();
while (line != null) {
lines.add(line);
line = reader.readLine();
}
Random r = new Random();
String randomLine = lines.get(r.nextInt(lines.size()));
JOptionPane.showMessageDialog(null,randomLine);
You only read the first line, and that's why you only get the first line. Try this..
String line = reader.readLine();
for (int i = 0; i < randomInt + 1; i++) {
line = reader.readLine();
}
What you are doing is reading a line from file, using that line to create a new Scanner with every iteration of loop and then read it back into line

Categories

Resources