Method: Taking a text file and storing it in 2d array - java

I have a text file that I have to store into a 2d array, with 3 columns, and numRecords rows, but is implemented within a method. The parameter numRecords is the number of values to read from the input file. I'm getting an InputMismatchException and I can't figure out why. Any help would be greatly appreciated
public String[][] readFile(File file, int numRecords) throws IOException {
int numRows = numRecords;
int numColumns = 3; // column 1 will be age, column 2 will be height, column 3 will be weight
String[][] data = new String[numRows][numColumns];
try {
Scanner readFile = new Scanner(file);
String line = null;
line = readFile.nextLine().trim();
while (readFile.hasNextLine()) {
line = readFile.nextLine();
String[] str = line.split(",");
for (String element : str) {
element = element + " ";
for (int row = 0; row < data.length; row++) {
for (int column = 0; column < data[0].length; column++) {
data[row][column] = Integer.toString(readFile.nextInt());
data[row][column] = Integer.toString(readFile.nextInt());
data[row][column] = Integer.toString(readFile.nextInt());
}
}
}
}
readFile.close();
}
catch (InputMismatchException e1) {
e1.printStackTrace();
}
return data;
}

You are generating element(s) from your scanner by reading line(s). You are also attempting to then read int(s) from the scanner and ignoring the elements you have read. Another possible issue is your code doesn't test that the file can actually be read before starting. And I would prefer try-with-Resources over explicitly closing the Scanner (as here you leak a file handle whenever there is an exception). Also, why read int(s) and convert them to a String - I would prefer reading into an int[][]. Putting that all together,
public int[][] readFile(File file, int numRows) throws IOException {
if (!file.exists() || !file.canRead()) {
System.err.printf("Cannot find file: %s%n", file.getCanonicalPath());
return null;
}
int numColumns = 3;
int[][] data = new int[numRows][numColumns];
try (Scanner readFile = new Scanner(file)) {
while (readFile.hasNextLine()) {
String line = readFile.nextLine();
String[] tokens = line.split(",");
int row = 0, column = 0;
for (String element : tokens) {
if (column >= numColumns) {
column = 0;
row++;
}
data[row][column] = Integer.parseInt(element);
column++;
}
}
} catch (InputMismatchException e1) {
e1.printStackTrace();
}
return data;
}

Related

How to append only one line/row for each iteration in appending values to CSV file in Java

I am having some issues in terms of appending data into my CSV file. The problem is that whenever I try to append data into my CSV file on a second time, the second value which is appended to the CSV file comes with the first appended value. It's like it brings the existing value with it when appending to the CSV file. Thus, because of this issue, it results into an array index out of bounds exception in this statement: cust[read2DStringIndex][newVarIndexer] = fromfile[g]; , the data of the CSV file repeats the existing values along with the latest appended values and also the first value is only displayed on my GUI table.
CSV File:
Table:
Here's my source code in writing and reading the CSV:
public void writeCustomerCSV(){ // this creates a CSV file which stores the inputs of the user
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\RALPH\\Documents\\Database Java CSV\\customers.csv",true)); // when I set append mode to true, cust[read2DStringIndex][newVarIndexer] = fromfile[g] results to index array out of bounds to 10
StringBuilder sb = new StringBuilder();
int y;
for(int x = 0; x < itemTo2D.length; x++){
if(itemTo2D[x][0] != null){
for(y = 0; y < itemTo2D[0].length; y++){
sb.append(itemTo2D[x][y]);
sb.append(",");
}
}
sb.append("-"); //separation for rows
sb.append(","); // separation for columns
}
bw.write(sb.toString());
bw.close();
}
catch (Exception ex){
}
}
public void readCustomerCSV(){ // reads the contents of the CSV file
String[][] twoDArray = new String[10][7];
int read2DStringIndex = 0;
int newVarIndexer = 0;
DefaultTableModel tblmodelll = (DefaultTableModel) mainTable.getModel(); // table
String[] fromfile = {}; // 1d string for getting the columns(7 columns) of the CSV file
int ak = 0;
int sk = 0;
try{
BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\RALPH\\Documents\\Database Java CSV\\customers.csv"));
String line;
while ((line = br.readLine()) != null){
fromfile = line.split(","); //separates the columns by a comma
for(int c = 0; c < fromfile.length; c++){
if(fromfile[c].equals("-")){
sk = 0;
ak++;
if(c > 0){
if(!fromfile[c-1].equals("-")){
id = id + 1;
}
}
} else{
twoDArray[ak][sk] = fromfile[c];
sk++;
}
}
}
} catch (Exception ex){
}
for(int g = 0; g < fromfile.length; g++){
if(fromfile[g].equals("-")){ //if there is a presence of a dash, it increments the read2DStringINdex (row index) of the 2D array
read2DStringIndex++;
newVarIndexer = 0;
}
else{
cust[read2DStringIndex][newVarIndexer] = fromfile[g]; //cust is the 2D array(declared universal) which is going to display the values to the table
newVarIndexer++;
}
}
for(int h = 0; h < cust.length; h++){ //prints cust (2D array) , just to check what data is being stored
for(int p = 0; p < cust[0].length; p++){
System.out.println(cust[h][p] + ",");
}
}
setrowcount = 0;
for(int r = 0; r < cust.length; r++){
if(setrowcount == 0){
tblmodelll.setRowCount(0);
}
try{
if(cust[r][0].equals("null") == false){
tblmodelll.addRow(cust[r]); //displays the cust(2D array) data to table
}
} catch(Exception e){
}
setrowcount++;
}
}
Is there something missing in my structure of the codes or is my logic in appending the values not right?
Your responses would indeed help me in resolving this issue.
Thank you very much.

How to determine how big is the treasure map (rows and columns) from a textfile?

I'd like to know how to figure out the rows and columns of a passed textfile.
Suppose the textfile looks like this:
X...................
....................
....................
....................
....................
....................
....................
....................
....................
..X.................
This textfile has 10 rows and 20 columns and I'm facing troubles with how to get those rows and columns for my constructor (DONT WORRY ABOUT "X" symbols). I just would like to know how to get rows and columns from the textfile/ would like to know how to figure out how big the map is.
I need help with the second constructor in the code:
import java.util.Scanner; // Required to get input
import java.io.File; // Required to get input from files
// A 2D treasure map which stores locations of treasures in an array
// of coordinates
public class TreasureMap{
int rows, cols; // How big is the treasure map
Coord [] treasureLocations; // The locations of treasures
Scanner kbd = new Scanner(System.in);
// Prompt the user for info on the treasure map and then create it
public TreasureMap(){
int numberOfTreasures = 0;
System.out.println("Enter map size (2 ints): ");
rows = kbd.nextInt(); cols = kbd.nextInt();
System.out.println("Enter number of treasures (1 int): ");
numberOfTreasures = kbd.nextInt();
treasureLocations = new Coord[numberOfTreasures];
for (int i = 0; i < numberOfTreasures; i++)
{
System.out.println("Enter treasure " + i + " location (2 ints): ");
rows = kbd.nextInt(); cols = kbd.nextInt();
treasureLocations[i] = new Coord(rows, cols);
}
}
// Read the string representation of a map from a file
public TreasureMap(String fileName) throws Exception{
Scanner data = new Scanner(new File(fileName));
int counter = 0;
while(data.hasNextLine())
{
counter++;
}
}
// true if there is treasure at the given (r,c) coordinates, false
// otherwise
// This method does not require modification
public boolean treasureAt(int r, int c){
for(int i=0; i<treasureLocations.length; i++){
Coord coord = treasureLocations[i];
if(coord.row == r && coord.col == c){
return true;
}
}
return false;
}
// Create a string representation of the treasure map
public String toString(){
String [][] map = new String[this.rows][this.cols];
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
map[i][j] = ".";
}
}
for(int i=0; i<treasureLocations.length; i++){
Coord c = treasureLocations[i];
map[c.row][c.col] = "X";
}
StringBuilder sb = new StringBuilder();
for(int i=0; i<rows; i++){
for(int j=0; j<cols; j++){
sb.append(map[i][j]);
}
sb.append("\n");
}
return sb.toString();
}
}
Here's some code you can use to read lines from a file:
File file = new File(fileName);
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
int rows = 0;
int cols = 0;
while ((line = br.readLine()) != null) {
// process the line
rows++;
cols = line.length(); // always the size of the last line in the file
}
}
br.close();
Based on your implementation, this would give you width and height of your input file.
public TreasureMap(String fileName) throws Exception{
Scanner data = new Scanner(new File(fileName));
int width = 0;
int height = 0;
while(data.hasNextLine())
{
String line = data.nextLine();
width = Math.max(width, line.length());
height++;
}
System.out.println(width + " x " + height);
}

summing column by column in java

i have file txt in desktop :
1 5 23
2 5 25
3 30 36
i want sum column by column 1 + 2 + 3 =... and 5 + 5...n and 23,...n
Scanner sc = new Scanner (file("patch");
while (sc.hasNextLine)
{
//each sum by column
}
help me please thanks
I would use a try-with-resources to clean up my Scanner using the File. Also, you could construct a Scanner around the line of input to get your int columns (that doesn't need to be closed because String(s) aren't closable anyway). Something like,
try (Scanner sc = new Scanner(new File("patch"))) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
Scanner row = new Scanner(line);
long sum = 0;
int count = 0;
while (row.hasNextInt()) {
int val = row.nextInt();
if (count == 0) {
System.out.print(val);
} else {
System.out.printf(" + %d", val);
}
sum += val;
count++;
}
System.out.println(" = " + sum);
}
} catch (IOException e) {
e.printStackTrace();
}
As the Scanner(String) Constructor Javadoc documents
Constructs a new Scanner that produces values scanned from the specified string.
Edit To sum the columns is a little trickier, but you could read everything into a multidimensional List<List<Integer>> like
try (Scanner sc = new Scanner(new File("patch"))) {
List<List<Integer>> rows = new ArrayList<>();
int colCount = 0;
while (sc.hasNextLine()) {
List<Integer> al = new ArrayList<>();
String line = sc.nextLine();
Scanner row = new Scanner(line);
colCount = 0;
while (row.hasNextInt()) {
colCount++;
int val = row.nextInt();
al.add(val);
}
rows.add(al);
}
for (int i = 0; i < colCount; i++) {
long sum = 0;
for (List<Integer> row : rows) {
sum += row.get(i);
}
if (i != 0) {
System.out.print("\t");
}
System.out.print(sum);
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
Edit 2 For efficiencies sake, you might prefer to use a Map like
try (Scanner sc = new Scanner(new File("patch"))) {
Map<Integer, Integer> cols = new HashMap<>();
while (sc.hasNextLine()) {
String line = sc.nextLine();
Scanner row = new Scanner(line);
int colCount = 0;
while (row.hasNextInt()) {
int val = row.nextInt();
if (cols.containsKey(colCount)) {
val += cols.get(colCount);
}
cols.put(colCount, val);
colCount++;
}
}
for (int i : cols.values()) {
System.out.printf("%d\t", i);
}
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
Please find the code. Please go through the comments.
This is one way of doing for your reference. I want you to try other ways to improve your knowledge rather just using this code.
int sums[] = null;
while (sc.hasNextLine())
{
String row = sc.next();// get first row
String[] values = row.split(" ");// split by space
if(null == sums)
{
sums = new int[values.length];// create sum array with first row size
}
int index = 0;
for (String value : values)
{
sums[index] = sums[index]+Integer.parseInt(value);//adding current row value to current sum
index++;
}
}
if(null != sums)
{
int index=0;
for (int sum : sums)
{
System.out.println("Sum of column "+index+" : "+sum);// Printing each column sum
index++;
}
}
If your file is CSV formatted, then split line by comma(",") and find number of columns based on split array length.
Like below:
String line = sc.next();
String[] lineArr = line.split(",");
int len = lineArr.length;
create array of arraylists of size len and store each column field in the respective arraylist.
finally, at the end apply sum on each arraylist to calculate sum of each column values.

NullPointerException while trying to initialize a 2d array

I am getting a nullPointerException trying to add values from a text file to a 2d array. The first 2 values determine the rows and columns. Any ideas what is throwing it. Ignore the exception handling, and the print statements. I am trying to get the array initialized then will go back and beef it up a bit.
public Help(String filename) throws FileNotFoundException,
InvalidFileFormatException {
this.filename = filename;
System.out.println("Reading in file: " + filename);
String number = "";
int row = 0;
int col = 0;
int count = 0;
try {
Scanner inputFile = new Scanner(new File(filename));
while (inputFile.hasNextInt()) {
row = Integer.parseInt(inputFile.next());
col = Integer.parseInt(inputFile.next());
System.out.println("Row : " + row);
System.out.println("Col : " + col);
baseMap = new double[row][col];
System.out.println(baseMap[2][4]);
for (int i = 0; i < baseMap.length; i++){
for (int j = 0; j < baseMap[i].length; j++){
baseMap[i][j] = Double.parseDouble(inputFile.next());
}
}
}
System.out.println(baseMap[2][4]);
} catch (Exception e) {
System.out.println(e.toString());
}
OUTPUT
Reading in file: sampleMap2.txt
Row : 5
Col : 5
0.0
Exception in thread "main" java.lang.NullPointerException
What value do you expect to see here;
baseMap = new double[row][col];
System.out.println(baseMap[2][4]);
How about if row == 1?
Also what if there is no more data at:
baseMap[i][j] = Double.parseDouble(inputFile.next());
Maybe you just don't have enough data.

Writing to a text file using Java gets cut short

I have a program reading from a text file (currently 653 lines long) all separated by a comma. But when I go to save the file to a new location, it only saves 490 lines. It also seems that the last line in the newly created text file is cut in half. Any ideas on what might be the problem?
Here is the code that I used to open and sort the data in the list:
try {
scanner = new Scanner(file);
// Put the database into an array and
// Make sure each String array is 13 in length
while (scanner.hasNext()) {
line = scanner.nextLine();
word = line.split(",");
if (word.length < 13) {
String[] word2 = {"","","","","","","","","","","","",""};
for (int i = 0; i < word.length; i++) {
word2[i] = word[i];
}
dataBaseArray.add(word2);
}
else {
dataBaseArray.add(word);
}
}
}
catch (FileNotFoundException exc) {
JOptionPane.showMessageDialog(this, "File cannot be found.", "error finding file", JOptionPane.ERROR_MESSAGE);
}
// Splitting the database into vacant numbers/dead lines/vacant cubicles
for (int i = 0; i < dataBaseArray.size(); i++) {
if (dataBaseArray.get(i)[8].equals("VACANT")) {
vacantNums.add(dataBaseArray.get(i));
}
else if (dataBaseArray.get(i)[4].equals("DEAD")) {
deadLines.add(dataBaseArray.get(i));
}
else if (dataBaseArray.get(i)[6].equals("") && dataBaseArray.get(i)[7].equals("")) {
vacantCubs.add(dataBaseArray.get(i));
}
else if (dataBaseArray.get(i)[7].equals("")) {
people.add(dataBaseArray.get(i));
}
else {
people.add(dataBaseArray.get(i));
}
}
// Resetting the DB Array to put the values back in it
dataBaseArray = new ArrayList<>();
// Ordering the arrays I want them to appear in the list
// Orering the people to appear in alphabetical order
Collections.sort(people, new Comparator<String[]>() {
#Override
public int compare(String[] strings, String[] otherStrings) {
return strings[7].compareTo(otherStrings[7]);
}
});
// Put the people in the DB Array
for (int i = 0; i < people.size(); i++) {
dataBaseArray.add(people.get(i));
}
// Put the vacant numbers in the AB Array
for (int i = 0; i < vacantNums.size(); i++) {
dataBaseArray.add(vacantNums.get(i));
}
// Put the vacant cubicles in the AB Array
for (int i = 0; i < vacantCubs.size(); i++) {
dataBaseArray.add(vacantCubs.get(i));
}
// Put the dead lines in the AB Array
for (int i = 0; i < deadLines.size(); i++) {
dataBaseArray.add(deadLines.get(i));
}
list = new String[dataBaseArray.size()];
// Add the DB Array to the list
for (int i = 0; i < list.length; i++) {
if (dataBaseArray.get(i)[8].equals("VACANT")) {
list[i] = "VACANT";
}
else if (dataBaseArray.get(i)[4].equals("DEAD")) {
list[i] = "DEAD";
}
else if (dataBaseArray.get(i)[6].equals("") && dataBaseArray.get(i)[7].equals("")) {
list[i] = "Vacant Cubicle";
}
else if (dataBaseArray.get(i)[7].equals("")) {
list[i] = dataBaseArray.get(i)[6];
}
else {
list[i] = dataBaseArray.get(i)[7] + ", " + dataBaseArray.get(i)[6];
}
}
// Populate the list
lstAdvance.setListData(list);
Here is what I used to save the file:
try {
saveFile = new FileWriter("Save Location");
String newLine = System.getProperty("line.separator");
for (int i = 0; i < dataBaseArray.size(); i++) {
for (int j = 0; j < dataBaseArray.get(i).length; j++) {
saveFile.append(dataBaseArray.get(i)[j] + ",");
}
saveFile.append(newLine);
}
}
catch (IOException exc) {
JOptionPane.showMessageDialog(this,"error", "error", JOptionPane.ERROR_MESSAGE);
}
Writing to a file is buffered. You have to close() or flush() your writer (saveFile) at the end of writing.
Even better: you should do close() on your writer in the finally block.
Try it using the FileWriter and BufferedWriter....
File f = new File("Your_Path");
FileWriter fw = new FileWriter(f);
BufferedWriter bw = new BufferedWriter(fw);
And yes..its very important to do bw.close() (Closing the Buffer)
See this question : Java FileWriter with append mode
The problem is that your FileWriter object needs to be "append mode" . Then, you append to the file with the "write" method rather than the "append" method. Use a finally catch clause to call "close" . You don't need to flush ( I dont think).

Categories