Reputation: 41
I am trying to create a program that reads a text file from JFileChooser, and then converts it into a 2d int array. the text file may look something like this:
000000
000000
001110
011100
000000
I need the file to be able to read a txt file of indefinite rows and columns. This is the code that I have tried, but my GUI does nothing when this happens, it breaks and will no longer exit on close.
To clarify, I want each single digit ( either a 1 or a 0 ) to print as an element of the array, and I want each line of the file to be a row in the array.
try {
File file = new File(String.valueOf(fc.getSelectedFile()));
Scanner reader = new Scanner(file);
cols = reader.nextLine().length();
while (reader.hasNextInt()) {
size++;
}
rows = size / cols;
int[][] iBoard = new int[rows][cols];
while (reader.hasNextInt()) {
for (int i = 0; i < iBoard.length; i++) {
for (int j = 0; j < iBoard[0].length; j++) {
iBoard[i][j] = reader.nextInt();
}
}
}
reader.close();
} catch (FileNotFoundException q) {
q.printStackTrace();
}
Upvotes: 0
Views: 253
Reputation: 9192
As already demonstrated this sort of thing is best done using a 2D ArrayList of Integer (ArrayList<ArrayList>>
) or 2D List Interface of Integer (List<List<Integer>>
). This is obviously the way to go since you don't need to read the data text file twice, once to get the number of actual data lines in file and again to retrieve the data. By using a collection mechanism like ArrayList or List you don't need to allocate a size for them, they can grow dynamically. If however you are still bent on utilizing a 2D integer array (int[][]
) then you can convert the collection to exactly that.
Here's my spin on it (utilizing the code scheme you have provided):
/**
* Allows the User to select a file using a file chooser navigation dialog.
* The selected file contents will then be placed into a 2D int Array. The
* file selected <u>must</u> contain 1 numerical value per text file Line,
* for example: <b>100100010</b>. Any blank lines in the file are ignored.<br>
*
* @param fileLocatedInFolder (Optional - String - Default is: "C:\") The
* directory path for where the JFileChooser lists files in when it opens.
* If nothing is supplied then the JFileChooser will start in the root
* directory of drive C.<br>
*
* @return (Two Dimensional int Array) A 2D int[][] array of the file contents.
* Each file line is an array row. Each numerical value in each file line is
* split into columnar digits for the 2D int array.
*/
public int[][] get2DArrayFromFile(String... fileLocatedInFolder) {
String fileChooserStartPath = "C:\\";
if (fileLocatedInFolder.length > 0) {
if (new File(fileLocatedInFolder[0]).exists() && new File(fileLocatedInFolder[0]).isDirectory()) {
fileChooserStartPath = fileLocatedInFolder[0];
}
}
JFileChooser fc = new JFileChooser(fileChooserStartPath);
fc.showDialog(this, "Open");
if (fc.getSelectedFile() == null) {
return null;
}
String filePath = fc.getSelectedFile().getAbsolutePath();
ArrayList<ArrayList<Integer>> rowsList = new ArrayList<>();
int[][] intArray = null;
// 'Try With Resources' use here to auto-close reader.
ArrayList<Integer> columnsList;
int row = 0;
int col = 0;
try (Scanner reader = new Scanner(fc.getSelectedFile())) {
String fileLine;
while (reader.hasNextLine()) {
fileLine = reader.nextLine();
fileLine = fileLine.trim(); // Trim the line
// If the file line is blank, continue to
// the next file line...
if (fileLine.isEmpty()) {
continue;
}
columnsList = new ArrayList<>();
col = 0;
String[] lineParts = fileLine.split("");
for (int i = 0; i < lineParts.length; i++) {
if (lineParts[i].matches("\\d")) {
columnsList.add(Integer.valueOf(lineParts[i]));
}
else {
System.err.println(new StringBuilder("Ivalid data detected ('")
.append(lineParts[i]).append("') on file line ")
.append((row + 1)).append(" in Column #: ").append((col + 1))
.append(System.lineSeparator()).append("Ignoring this data cell!")
.toString());
}
col++;
}
row++;
rowsList.add(columnsList);
}
}
catch (FileNotFoundException ex) {
Logger.getLogger("get2DArrayFromFile() Method Error!")
.log(Level.SEVERE, null, ex);
}
//Convert 2D Integer ArrayList to 2D int Array
intArray = new int[rowsList.size()][rowsList.get(0).size()];
for (int i = 0; i < rowsList.size(); i++) {
for (int j = 0; j < rowsList.get(i).size(); j++) {
intArray[i][j] = rowsList.get(i).get(j);
}
}
rowsList.clear();
return intArray;
}
And to use the above method:
int[][] iBoard = get2DArrayFromFile();
// Display 2D Array in Console Window:
if (iBoard != null) {
for (int i = 0; i < iBoard.length; i++) {
System.out.println(Arrays.toString(iBoard[i]).replaceAll("[\\[\\]]", ""));
}
}
If your data file is as you've show it:
000000
000000
001110
011100
000000
Then the output to console window will be:
0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0
0, 0, 1, 1, 1, 0
0, 1, 1, 1, 0, 0
0, 0, 0, 0, 0, 0
Upvotes: 0
Reputation: 53
Here is how I did it.
package com.tralamy.stackoverflow;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
public class FileToArray {
public static void main(String[] args) throws IOException {
// In your case, replace "array.txt" by String.valueOf(fc.getSelectedFile())
File file = new File("array.txt"); // Creating a new File for the array
Scanner fileScan = new Scanner(file); // Creating a Scanner Object from the file
ArrayList<ArrayList<Integer>> arrays = new ArrayList<>(); // The 2d Array
// For each line of the file
while (fileScan.hasNextLine()) {
String line = fileScan.nextLine(); // Store the line content to a String variable
ArrayList<Integer> array = new ArrayList<>(); // One dimension Array of Integer
// For each character in the line
for (Character ch : line.toCharArray()) {
/*
* Integer.parseInt parse a String to a integer
* To get a string from a Character I use toString method
* I then add the value to the array*/
array.add(Integer.parseInt(ch.toString()));
}
arrays.add(array); // add the one dimension to the two dimensions array
}
fileScan.close(); // Close the scanner
// To print the result, uncomment the line below
System.out.println(arrays);
}
}
000000
000000
001110
011100
000000
Upvotes: 1
Reputation: 556
Instead of trying to read each int
at a time, you could save each line into a List<String>
. Then iterate through this list, getting each char
of each String
and putting it into your 2D Array.
Upvotes: 0