ArrayIndexOutOfBound when parsing int from string array - java

I am new to StackExchange so I will do my best at making this question as understable as possible. I am trying to take all Integers from a String Array created from a .csv file. The file looks like so,
type,name,untiprice,quantity
Bitem,toothpaste,1.50,2
Fitem,eggs,2.50,1
and so on...
Everything works perfectly until I try to add the numbers to the array. The output returns a ArrayIndexOutOfBoundsException. I made the MAX_SIZE of this array = 100. The amount of integers in the text file is no more than 8. I don't understand why this is problem is happening. Are my for-loops completely wrong or is there more to the problem?
public static void loadNums()
{
String inputFile=("/Users/user1/Desktop/list.csv");
File file = new File(inputFile);
Scanner scanFile = null;
try{
scanFile =new Scanner(file);
}catch(NumberFormatException | FileNotFoundException exception){
System.out.println("Error");
}
if (scanFile != null)
{
String[] numStrs = scanFile.nextLine().split(",");
int[] num = new int[numStrs.length];
for (int i =0; i <numStrs.length; i++)
{
if (i ==0)
{
System.out.println("Numbers");
}
else
{
numStrs = scanFile.nextLine().split("\\d+.,\\d+");
for (int j =0; j <numStrs.length; j++)
{
num[i] = Integer.parseInt(numStrs[i]);
}
System.out.println(num[i]);
}
}
}

You try to parse the second array numStrs with the first index i :
num[i] = Integer.parseInt(numStrs[i]);
So instead to that use this, change the numStrs[i] with numStrs[j]:
num[i] = Integer.parseInt(numStrs[j]);
Hope this can help you.

Related

is there a way to read values from a file int an array and initialize those value?

import java.io.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try {
File file = new File("C:\\Users\\HIM\\IdeaProjects\\File Tutorial\\src\\quad.txt");
Scanner scanner = new Scanner(file);
double a , b, c;
double[] arr = new double[3];
for(int i = 0; i < arr.length; i++) {
while (scanner.hasNextLine()) {
arr[i] = scanner.nextInt();
System.out.println(arr[i]);
}
}
a = arr[0];
System.out.println(a);
b = arr[1];
System.out.println(b);
c = arr[2];
System.out.println(c);
} catch (Exception e){
System.out.println("Not Found");
}
}
}
i used this code, but from the loop that transferred the values 2, 3, 4, into the array it was read successful but i tried initializing those array values into a,b,c, but it only reads the last value and assign it to a.
You don't say what your input file looks like, so it's hard to tell you exactly what's wrong, but I suspect the issue is you are using hasNextLine in your loop, but nextInt when you read. This won't behave in the way you expect for input like this, for example:
1 2 3
Notice that there is one line, so hasNextLine will return false because, while there are multiple ints, there is only one line.
What you probably want instead is Scanner#hasNextInt
In addition, this logic is probably not correct:
for(int i = 0; i < arr.length; i++) {
while (scanner.hasNextLine()) {
arr[i] = scanner.nextInt();
System.out.println(arr[i]);
}
When a Scanner moves to the next token, you cannot go back. So you can only read from it once without creating a new scanner.
What you likely want is the following:
int i = 0;
while (scanner.hasNextInt()) {
arr[i] = scanner.nextInt();
System.out.println(arr[i]);
i++;
}
This will go through the scanner once and correctly populate your values.
for(int i = 0; i < arr.length; i++) {
while (scanner.hasNextLine()) {
arr[i] = scanner.nextInt();
System.out.println(arr[i]);
}
}
Look at the inner loop. You're running while(scanner.hasNextLiine() however i is never getting iterated while you read the file. As a result, you read the entire file, but always put it into arr[i=0].
A better solution may be
int i = 0;
while(scanner.hasNextLine() && i < arr.length){
arr[i++] = scanner.nextInt();
}
Which will combine the functionality of your while and for loop. Another alternative:
for(int i = 0; i < arr.length && scanner.hasNextLine(); i++){
arr[i] = scanner.nextInt();
}
Chris's answer is also valid. nextInt and hasNextLine aren't the same thing. But in this case I'm assuming your file has ints on every line.

Java: Most Efficient Way to Get Input Integer Array

I'm working on a problem that requires me to store a very large amount of integers into an integer array. The input is formatted so that one line displays the amount of integers and the next displays all of the values meant to be stored. Ex:
3
12 45 67
In the problem there is closer to 100,000 integers to be stored. Currently I am using this method of storing the integers:
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] iVau = new int[n];
String[] temp = scanner.nextLine().split(" ");
for(int i = 0; i < n; i++) {
iVau[i] = Integer.parseInt(temp[i]);
}
This works fine, however the problem I am solving has a strict time limit and my current solution is exceeding it. I know that there is a more efficient way to store this input using buffered readers and input streams, but I don't know how to do it, can someone please show me.
The way you are using Scanner makes your program save a String containing the whole numbers at once, in memory. With 100000 numbers in the 2nd line of your input, it is not so efficient, you could read numbers one after the other without keeping the previous one in memory. So, this way, avoiding using Scanner.readLine() should make your program run faster. You will not have to read the whole line one time, and read a 2nd time this String to parse the integers from it: you will do both of these operations only once.
Here is an example. The method testing() does not use any Scanner. The method testing2() is the one you provided. The file tst.txt contains 100000 numbers. The output from this program, on my Mac Mini (Intel Core i5#2.6GHz) is:
duration without reading one line at a time, without using a Scanner instance: 140 ms
duration when reading one line at a time with a Scanner instance: 198 ms
As you can see, not using Scanner makes your program 41% faster (integer part of (198-140)/140*100 equals 41).
package test1;
import java.io.*;
import java.util.*;
public class Test {
// Read and parse an Int from the stream: 2 operations at once
private static int readInt(InputStreamReader ir) throws IOException {
StringBuffer str = new StringBuffer();
int c;
do { c = ir.read(); } while (c < '0' || c > '9');
do {
str.append(Character.toString((char) c));
c = ir.read();
} while (!(c < '0' || c > '9'));
return Integer.parseInt(str.toString());
}
// Parsing the input step by step
private static void testing(File f) throws IOException {
InputStreamReader ir = new InputStreamReader(new BufferedInputStream(new FileInputStream(f)));
int n = readInt(ir);
int [] iVau = new int[n];
for (int i = 0; i < n; i++) iVau[i] = readInt(ir);
ir.close();
}
// Your code
private static void testing2(File f) throws IOException {
Scanner scanner = new Scanner(f);
int n = scanner.nextInt();
int[] iVau = new int[n];
scanner.nextLine();
String[] temp = scanner.nextLine().split(" ");
for(int i = 0; i < n; i++)
iVau[i] = Integer.parseInt(temp[i]);
scanner.close();
}
// Compare durations
public static void main(String[] args) throws IOException {
File f = new File("/tmp/tst.txt");
// My proposal
long t = System.currentTimeMillis();
testing(f);
System.out.println("duration without reading one line at a time, without using a Scanner instance: " + (System.currentTimeMillis() - t) + " ms");
// Your code
t = System.currentTimeMillis();
testing2(f);
System.out.println("duration when reading one line at a time with a Scanner instance: " + (System.currentTimeMillis() - t) + " ms");
}
}
NOTE: creating the input file is done this way, with bash or zsh:
echo 100000 > /tmp/tst.txt
for i in {1..100000}
do
echo -n $i" " >> /tmp/tst.txt
done
I believe this is what you're looking for. A BufferedReader can only read a line at a time, so it is necessary to split the line and cast Strings to ints.
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
int n = Integer.parseInt(br.readLine());
int[] arr = new int[n];
String[] line = br.readLine().split(" ");
for (int i = 0; i < n; i++) {
arr[i] = Integer.parseInt(line[i]);
}
} catch (IOException e) {
e.getStackTrace();
}
Just a thought, String.split returns an array of Strings. You say the input can be around 100,000 values. So in order to split the array in this way, String.split must be iterating through each element. Now in parsing the new array of strings to Integers you have iterated through the collection twice. You could do this in one iteration with a few small tweaks.
Scanner scanner = new Scanner(System.in);
String tmp = scanner.nextLine();
scanner = new Scanner(tmp);
for(int i = 0; scanner.hasNextInt(); i++) {
arr[i] = scanner.nextInt();
}
The reason for linking the scanner to a String instead of leaving it on System.in is so that it ends properly. It doesn't open System.in for user input on the last token. I believe in big O notation this is the difference between O(n) and O(2n) where the original snippet is O(2n)
I am not quite sure why OP has to use Integer.parseInt(s) here since Scanner can just do the parsing directly by new Scanner(File source).
Here is a demo/test for this idea:
public class NextInt {
public static void main(String... args) {
prepareInputFile(1000, 500); // create 1_000 arrays which each contains 500 numbers;
Timer.timer(() -> readFromFile(), 20, "NextInt"); // read from the file 20 times using Scanner.nextInt();
Timer.timer(() -> readTest(), 20, "Split"); // read from the file 20 times using split() and Integer.parseInt();
}
private static void readTest() {
Path inputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
try (Scanner scanner = new Scanner(new File(inputPath.toString()))) {
int n = Integer.valueOf(scanner.nextLine());
int[] iVau = new int[n];
String[] temp = scanner.nextLine().split(" ");
for (int i = 0; i < n; i++) {
iVau[i] = Integer.parseInt(temp[i]);
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void readFromFile() {
Path inputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
try (Scanner scanner = new Scanner(new File(inputPath.toString()))) {
while (scanner.hasNextInt()) {
int arrSize = scanner.nextInt();
int[] arr = new int[arrSize];
for (int i = 0; i < arrSize; ++i) {
arr[i] = scanner.nextInt();
}
// System.out.println(Arrays.toString(arr));
}
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
private static void prepareInputFile(int arrCount, int arrSize) {
Path outputPath = Paths.get(Paths.get("").toAbsolutePath().toString().concat("/src/main/java/io/input.txt"));
List<String> lines = new ArrayList<>();
for (int i = 0; i < arrCount; ++i) {
int[] arr = new int[arrSize];
for (int j = 0; j < arrSize; ++j) {
arr[j] = new Random().nextInt();
}
lines.add(String.valueOf(arrSize));
lines.add(Arrays.stream(arr).mapToObj(String::valueOf).collect(Collectors.joining(" ")));
}
try {
Files.write(outputPath, lines);
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
}
Locally tested it with 1_000 arrays while each array has 500 numbers, reading all the elements cost about: 340ms using Scanner.nextInt() while OP's method about 1.5ms.
NextInt: LongSummaryStatistics{count=20, sum=6793762162, min=315793916, average=339688108.100000, max=618922475}
Split: LongSummaryStatistics{count=20, sum=26073528, min=740860, average=1303676.400000, max=5724370}
So I really have doubt the issue lies in the input reading.
Since in your case you are aware of the total count of elements all that you have to do is to read X integers from the second line. Here is an example:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int count = in.nextInt();
int array[] = new int[count];
for (int i = 0; i < count; i++) {
array[i] = in.nextInt();
}
}
If this is not fast enough, which I doubt, then you could switch to the use of a BufferedReader as follows:
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
int count = Integer.parseInt(in.readLine());
int array[] = new int[count];
for (int i = 0; i < count; i++) {
int nextInteger = 0;
int nextChar = in.read();
do {
nextInteger = nextInteger * 10 + (nextChar - '0');
nextChar = in.read();
} while (nextChar != -1 && nextChar != (int)' ');
array[i] = nextInteger;
}
}
In your case the input will be aways valid so this means that each of the integers will be separated by a single whitespace and the input will end up with EoF character.
If both are still slow enough for you then you could keep looking for more articles about Reading Integers in Java, Competative programming like this one: https://www.geeksforgeeks.org/fast-io-in-java-in-competitive-programming/
Still my favorite language when it comes to competitions will always be C :) Good luck and enjoy!

Java 2d Array unable to edit value and properly return element back null values

My knowledge with java language is very new. Most of my knowledge are from googling up on how to do things. I've been working on a console program in java that uses a switch statement. The entire program utilizes an String [20][5] array. I've written the code to now be able to add entry, save array to file, load entries from file into the array.
The problems now is edit and removing entries. I am able to return values to null but it'll look like this [[null], [null, null, null, null, null].
I want the value to return to [null, null, null, null, null], [null, null, null, null, null].
The Edit entry some reasons return an java.lang.ArrayIndexOutOfBoundsException:1 .
Could someone point out my error? Also the Array is globally declare.
public static String[][] rem(){
Scanner input = new Scanner(System.in);
int x,y=0;
//for(int i=0;i<array.length;i++){
//if(array[i][0]!=null){
System.out.println(Arrays.deepToString(array));//}
//}
System.out.println("Which entry would you like to remove? "
+ "\n" + "Enter number 0 - 20");
x = input.nextInt();
array[x][y]=null;
return array;}
public static String[][] edit(){
Scanner input = new Scanner(System.in);
String k;
int j;
int g;
// for(int i=0;i<array.length;i++){
//if(array[i][0]!=null){
//System.out.println(Arrays.deepToString(array));}
//}
System.out.println("Which entry would you like to edit? "
+ "\n" + "Enter number 0 - 20");
j = input.nextInt();
System.out.println("What would you like to edit? "
+"\n" + "Enter number 0 - 5");
g = input.nextInt();
System.out.println("You are now editing.");
k = input.next();
array[j][g] = k;
return array;}
Update
I think I figure my issue. The array properly edit values I manually input. It's when I load data into the array that causes problem because when it loads data it loads as String []. I need a code that will load the data as String[][] or as array of arrays.
public static String[][] load()throws FileNotFoundException, IOException{
menu();
copyFile();
String file = ("c:/temp/Address.txt");
Scanner scan = new Scanner(new FileReader(file));
// initialises the scanner to read the file file
//String[][] entries = new String[100][3];
// creates a 2d array with 100 rows and 3 columns.
//int i = 0;
while(scan.hasNextLine()){
array[i][i] = scan.next().split("," , "\t");
i++;
}
//loops through the file and splits on a tab
//for (int row = 0; row < array.length; row++) {
// for (int col = 0; col < array[0].length; col++) {
// if(array[row][col] != null){
// System.out.print(array[row][0] );
// }
// }
// if(array[row][0] != null){
// System.out.print("\n");
//}
// }
//prints the contents of the array that are not "null"
selectMenu();
return array;}
Update 2
I have found the solution to solving the loading data issue. The solution is simple! I'll leave the code here for reference. Though, all of the codes could use some beautifying.
public static String[][] load()throws FileNotFoundException, IOException{
menu();
copyFile();
String file = ("c:/temp/Address.txt");
Scanner scan = new Scanner(new FileReader(file));
FileReader fr = new FileReader("c:/temp/Address.txt");
BufferedReader br = new BufferedReader(fr);
//int j=0;
//int lineNo = 0;
//String line = br.readLine();
//while(line!=null)
//{
//for(int i = 0; i < 5; i++)
//{
//array[lineNo][i] = line.substring(i,4);
//}
// lineNo++;
//line = br.readLine(); // This is what was missing!
//}
//while(scan.hasNextLine()){
//while(scan.hasNext()){
//for(j=0;j<5;j++){
for(int i = 0; i < 20; ++i){
for(int j = 0; j < 5; ++j)
{
if(scan.hasNext())
{
array[i][j] = scan.next();
//i++;
//j++;
}
//i++;
}
}
selectMenu();
return array;}
Update 3
So after figuring out on how to use the delimiter it sorts of give me a weird issue. It adds return at the end of the column. [null, null, null, null, null return]. I used ",|\n" as my delimiter. Is there a better method? Update: Added a .trim(); solve the final issue with load. Now it's perfected in its current job. Though, I'm sure there might be less primitive methods.
public static String[][] load()throws FileNotFoundException, IOException{
copyFile();
//delimiter removes the comma or return to the next line. "\n" new line
Scanner scan = new Scanner(new FileReader(file)).useDelimiter(",|\n");
for(int i = 0; i < 20; ++i){
for(int j = 0; j < 5; ++j){
if(scan.hasNext())
array[i][j] = scan.next().replace(",", "").trim();
}
}
System.out.println("File loaded successfully!!");
scan.close();
return array;}
This is an off by one error, very subtle mistake:
Although you have 20 rows and 5 columns, arrays use a 0 based index(start counting from 0 instead of 1).
Use your fingers to count from 0 - 5 and you will see that there are actually 6 numbers instead of 5 which is causing your OutOfBoundsException as you don't have a 6th element.
Therefore to access your rows and columns, the range should be between:
0 - 19 (for the columns) and 0 - 4 (for the rows)
Or
1 - 20 (for the columns) and 1 - 5 (for the rows) and then subtract 1 from your scanners input since remember arrays use 0 based index.
update for the file reading:
public static String[][] load() {
try{
FileReader fr = new FileReader("c:/temp/Address.txt");
BufferedReader bf = new BufferedReader(fr);
String presentLine = "";
for(int i = 0; i < 20; i++) {
for(int j = 0; i < 5; j++) {
if ((presentLine = bf.readLine()) != null) {
array[i][j] = presentLine;
}
}
}
} catch(Exception e) {
System.out.println(e);
}
selectMenu();
return array;
}
Although this could be made way better but it's okay.
You could store 20 and 5 as static variables called rows and columns respectively to avoid using hard coded numbers.

Read and Sort a file to array Java

I'm attempting to write a program that would read a file "data.txt" which has an undefined amount of numbers in random order, separated by line. It would add these numbers into an array and print out the numbers in one line, each separated by a comma "x, x1". Then on the next line it would print out (in the same format) the list of numbers which has been sorted from smallest to largest size.
Data type is integer.
Currently, I have coded for 3 methods which would allow the array to be sorted (I think they have no error).
I've created another method to read the file and am using a two-step process - once to figure out the number of lines in the file (I ask that this two-step process remain). This method seems to have trouble returning the "lineCount" and apparently I need to make this variable an array (which I find bizarre). How can I fix this code?
You may notice that my method for printing is empty; I have not figured out a way to print the array so that each number is separated by a comma. How do I code for this?
My code so far:
import java.util.*;
import java.io.*;
public class SortAndSearch {
public static void main(String[] args) {
readFile2Array();
printArray();
selectionSort();
printArray();
}
public static void printArray(int[] a) {
}
public static void selectionSort(int[] a) {
int minI = 0;
for (int k = 0; k < a.length - 1; ++k) {
minI = findMinIdx(a, k); // findMinIdx at k-th
swapElement(a, k, minI);// swapElement at k-th
}
}
public static int findMinIdx(int[] a, int k) {
int minIdx = k;
for (int i = k + 1; i < a.length; ++i)
if (a[i] < a[minIdx])
minIdx = i;
return minIdx;
}
public static void swapElement(int[] a, int i, int j) {
int temp;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static int[] readFile2Array(String fileName) {
File dat = new File("data.txt");
int lineCount = 0;
int[] a = new int[lineCount];
int i;
try{ Scanner sc = new Scanner(dat);
while (sc.hasNextLine()){ //first read to count -> int lineCount;
lineCount++;
return lineCount; //I have trouble with this line
}
while (sc.hasNextLine()){ //second read to array -> hasNext(),
a[i] = sc.nextInt();
return a;
}
}
catch (FileNotFoundException e) {
System.out.println("File cannot be opened");
e.printStackTrace();
}
}
public static int binarySearch(int[] arr, int val){
int minIdx, maxIdx, index = -1;
while(){ int middleIdx = (minIdx + maxIdx)/2;
if( arr[???] ==val){
index = middleIdx;
break } // update minIdx, maxIdx //if smaller then cut right, if larger then cut left
}
return index; }
}
The last method in the program would attempt to locate the element number of a user inputted number by using this (pseudo)code:
1. Let ‭min = 0‬ and ‭max = n-1‬ (where n is the array’s length)‬‬‬‬
2. If ‭max < min‬, then stop: ‭target‬ is not present in ‭array‬. return ‭false‬.‬‬‬‬‬‬‬‬
3. Compute ‭guess‬ as the average of ‭max‬ and ‭min‬, rounded down (so that it is an integer).‬‬‬‬‬‬
4. If ‭array[guess]‬ equals ‭target‬, then stop. You found it! Return ‭guess‬.‬‬‬‬‬‬
5. If the guess was too low, that is, ‭array[guess] < target‬, then set ‭min = guess + 1‬.‬‬‬‬
6. Otherwise, the guess was too high. Set ‭max = guess - 1‬.‬‬
7. Go back to step 2.
How would I code for this?
I would really appreciate any help in any area of this program!
Managed to fix the first part of the code:
readFile2Array method:
public static int[] readFile2Array(String fileName) {
try {
int lineCount = 0;
Scanner sc = new Scanner(new File("data.txt"));
while (sc.hasNext()) { // first read to count -> int lineCount;
lineCount++; // second read to array -> hasNext(),
sc.nextLine();
}
sc.close();
sc = new Scanner(new File("data.txt"));
int[] x = new int[lineCount];
int n = 0;
while (sc.hasNext()) {
x[n] = Integer.parseInt(sc.nextLine());
n++;
}
sc.close();
return x;
} catch (FileNotFoundException e) {
System.out.println("File cannot be opened");
e.printStackTrace();
}
return null;
}
Print array separated by comma:
public static void printArray(int[] a) {
try {
int lineCount = 0;
Scanner sc = new Scanner(new File("data.txt"));
while (sc.hasNext()) {
lineCount++;
sc.nextLine();
}
sc.close();
for (int i = 0; i < a.length; ++i) {
System.out.print(a[i]);
if (i < lineCount-1) System.out.print(", ");
}
} catch (FileNotFoundException e) {
System.out.println("File cannot be opened");
}
System.out.println();
}
Last method is still a mystery to me though!
I agree with VGR that you haven't actually asked a question, but by reading your code I guess that you were describing what you wanted to achieve...
There are some flaws in your readFile2Array-method, which might solve the problem:
1)
int lineCount = 0;
int[] a = new int[lineCount]; //The size of a will always be 0, so you can't add anything to it, even though you are trying to do this later. Consider using a List instead, as the size of the list can increase dynamically.
2)
while (sc.hasNextLine()){ //first read to count -> int lineCount;
lineCount++;
return lineCount; //I have trouble with this line
}
//The problem is the return type: You method signature states that you will return int[], but here you are trying to return an int.
//It will also just increase lineCount once and try to return this.
3)
//Your scanning will be at the 2nd line because of 2) and not going through the entire file again. To do this you need to create a new instance of Scanner. And the int[] a has a size of 0 at this point.
while (sc.hasNextLine()){ //second read to array -> hasNext(),
a[i] = sc.nextInt();
return a;
}
So in order to solve this you should refactor your code to something like:
public static List<Integer> readFile2Array(String fileName) {
File dat = new File("data.txt");
List<Integer> a = new ArrayList<>();
try{ Scanner sc = new Scanner(dat);
while (sc.hasNextLine()){
a.add(sc.nextInt());
}
sc.close(); //Always remember to close, when done :)
System.out.println("Added " + a.size() + " lines to the list.");
return a;
} catch (FileNotFoundException e) {
System.out.println("File cannot be opened");
e.printStackTrace();
return new ArrayList<>();
}
}
What I changed:
removed the lineCount as this is implicit stored in the size of the list called a.
Changed the int[] a to a List as this always will allow adding elements by increasing its size when needed.
Removed i as was never used, only initialized.
Removed the first while-loop as we don't need to know the amount of lines that is going to be added.
Added a return-statement in the catch-closure. We need to return something (even an empty array or maybe the not-yet-finished array)
I hope this helps. :)
I'm glad you got that part working. :)
To print out the array, it will be best to use whatever data you have of the array. By calling a.length, you don't have to count the number of lines from the input again, which you are not guaranteed are still the same if the input has changed in the mean time.
So this piece of code should do the trick:
public static void printArray(int[] a) {
for (int i = 0; i < a.length; ++i) {
System.out.print(a[i]);
if (i < a.length-1) System.out.print(", ");
}
System.out.println();
}

Read text file for integers and storing to array using scanner and exceptions

I'm trying to loop through a text file for integers and store integers found into an array.
Using a try-catch to determine which words are integers and which are not using InputMismatchException, removing the non-int strings from the input stream. As well as a NoSuchElementException for blank lines in the file.
My main issue is storing the integers and printing those integers in the array, in my second method :o . It also appears my loop is also recording non-ints as null as well. They aren't suppose be stored into the array.
public static void main(String[] commandlineArgument) {
Integer[] array = ReadFile6.readFileReturnIntegers(commandlineArgument[0]);
ReadFile6.printArrayAndIntegerCount(array, commandlineArgument[0]);
}
public static Integer[] readFileReturnIntegers(String filename) {
Integer[] array = new Integer[1000];
// connect to the file
File file = new File(filename);
Scanner inputFile = null;
try {
inputFile = new Scanner(file);
}
// If file not found-error message
catch (FileNotFoundException Exception) {
System.out.println("File not found!");
}
// if connected, read file
if (inputFile != null) {
// loop through file for integers and store in array
while (inputFile.hasNextLine()) {
for(int i = 0; i<array.length; i++)
{
try{
array[i] = inputFile.nextInt();
}
catch(InputMismatchException excep1)
{
String word = inputFile.next();
}
catch(NoSuchElementException excep2){
}
}
}
}
return array;
}
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
//prints number of integers from file
//prints each integer in array
}
}
The approach taken in the first method is a bit flawed, since you're incrementing the i variable whether or not an integer is read.
So for example, if the file looked like this:
4
Hello
5
e
7
The beginning of your array would look like
[4, null, 5, null, 7...]
So you will end up with an array of size 1000, which has nulls at unpredictable places in there.
A slightly better approach would be this:
Keep a separate count variable that says how many integers you actually read.
Add items to the array at index count and not at i (since i just says how many lines you've looked at, whereas count will tell you how many integers you've come across).
When you're finished reading them, either
pass the count variable to the method that prints the array (so it knows only to look at the first count items), or
just copy the entire array into a new array of size count.
Example incorporating this into your code:
if(inputFile != null) {
// the number of integers we've read so far
int count = 0;
// loop through file for integers and store in array
while(inputFile.hasNextLine()) {
for(int i = 0; i < array.length; i++) {
try {
array[count] = inputFile.nextInt();
count++;
} catch(InputMismatchException excep1) {
String word = inputFile.next();
} catch(NoSuchElementException excep2) {
}
}
}
}
Then to copy into a correctly sized array,
Integer[] newArray = new Integer[count];
for(int i = 0; i < count; i++) {
newArray[i] = array[i];
}
and just return newArray instead of array.
Your print method will then simply have the same signature and functionality you'd expect:
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
for(int i = 0; i < array.length; i++) {
// print the number at array[i], and whatever else you want to print
}
}
This is probably the better approach, as you can still keep all the method signatures the same, and don't need to mess around with returning multiple variables or changing global state.
Or alternatively, if you don't want to copy the relevant bits into a new array, then you could just pass the count variable somehow to your second method, and do something like
for(int i = 0; i < count; i++) {
System.out.println("\tindex = " + i + ", element = " + array[i]);
}
Key difference there is you're iterating up to count, and not up to array.length.
You would need to find a way to return that from your first method along with the array (or maybe set a static variable somewhere), and you would then need to change the signature of your second method to be
public static void printArrayAndIntegerCount(Integer[] array, int count, String filename) {
...
}
Assuming all you logic for reading integers from file are correct and also hoping this is kind of home work. Though the following implementation is not the right approach, it just solves your purpose. All we are doing here is iterating all the elements in the array until it reaches the null and keep writing them into a buffer.
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
StringBuilder sb = new StringBuilder();
int count = 0;
for(Integer i : array) {
if(i != null) {
count++;
sb.append("index = ").append(i).append(", element = ").append(array[i]).append("\n");
} else {
break;
}
}
System.out.println("number of integers in file \""+filename+"\" = "+count);
System.out.println(sb);
}
Replace your catch statement with:
catch(InputMismatchException excep1)
{
String word = inputFile.next();
i-=1;
}
You were incrementing the array counter if it found a word. I have run my own test and this worked for me to fix your issue.
public static void printArrayAndIntegerCount(Integer[] array, String filename) {
String message = "";
int i = 0;
while(i < array.length && array[i]!=null){
message = message + "index = "+i+", element = "+array[i]+"\n";
i+=1;
}
System.out.println("number of integers in file \""+filename+"\" = "+i);
System.out.println(message);
}

Categories