Cannot assign a substring from a file to my array - java

I have a file with 50 states and capitals in this format:
Alabama,Tallahasee,
Wisconsin,Madison,
........
I am trying to assign the states and capitals to seperate arrays and I am having a problem with the for loop. My code is as follows:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class StatesAndCapitals {
public static void main(String[] args) throws FileNotFoundException {
FileInputStream is = new FileInputStream("capitals.txt");
Scanner input = new Scanner(is);
String[] states = new String[50];
String[] capitals = new String[50];
for (int i = 0; i < states.length; i++){
int a = states[i].lastIndexOf(",");
String states1 = states[i].substring(0, a);
states[i] = states1;
input.nextLine();
}//end for loop
System.out.println(states);
}
}
The error I am getting is
Exception in thread "main" java.lang.NullPointerException
at StatesAndCapitals.main(StatesAndCapitals.java:12)
any help would be appreciated.

When you do
states[i].lastIndexOf(",");
you're analyzing the content of states[i]. But that is your destination array, and not the source containing the text. The source is what is returned from input.nextLine(), which should be the first thing you should do at each iteration:
for (int i = 0; i < states.length; i++){
String currentLine = input.nextLine();
// now extract the data from current line, and store them in the arrays.
}

for (int i = 0; i < states.length; i++){
int a = states[i].lastIndexOf(",");
String states1 = states[i].substring(0, a);
states[i] = states1;
input.nextLine();
}//end for loop
This whole loop is backwards. When you first enter at i = 0 you attempt to take a substring of your states array which has never seen any sort of assignment. You then work on that substring within the loop before ending with input.nextLine(); which is never actually used.
The input variable, when used correctly will actually hold data from the file you open and will allow you to manipulate strings with substring. You need to reorder and fix your loop.

The default value for an object is null.
String[] states = new String[50]; //<-- you declare an array that can holds 50 Strings but they're actually null if you don't initialize them.
So when doing states[i].lastIndexOf(","); it throws a NPE.
Same behavior for your capitals array.
Read the Default Values section.
You need to store the datas in a String variable first :
for (int i = 0; i < states.length; i++){
String data = input.nextLine();
// Now process with data and add corresponding parts to states and capitals array
}//end for loop
And then process on this String and add it to the corresponding array.
Not that if you don't have enough lines in your file (less than 50), it will throw java.util.NoSuchElementException because no more lines are found.
You can add this condition to the loop : for (int i = 0; i < states.length && input.hasNextLine(); i++){
When you will get this working correctly, I suggest you to deal with a List.

Related

Java Reading Strings to a 2D Boolean Array

I am trying to read a txt file which consists of # and spaces to a 2D boolean array, so that technically a # represents true and a space represents false.
With the help of similar posts i got together a code, although they were reading integers to an array.
My code is:
public static void main(String[] args) {
String x;
String y;
Scanner fileName = null;
try {
fileName = new Scanner(new File("C:/Users/USER/Desktop/hashtag.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
x = fileName.nextLine();
y = fileName.nextLine();
boolean[][] cells = new boolean[x][y];
String finalX = fileName.nextLine();
String finalY = fileName.nextLine();
cells[finalX][finalY] = true;
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
if (cells[i][j])
System.out.print("#");
else
System.out.print(" ");
}
System.out.println();
}
}
In my code where I have written boolean[][] cells = new boolean[x][y];
It says the [x] and [y] requires an int, but found a string. The same issue is for cells[finalX][finalY] = true;
I tried parsing i.e. Integer.parseInt(x) however this gets me an error:
Exception in thread "main" java.lang.NumberFormatException: For input string: "#####################"
At what point is my issue? If I parse to an Int, then it can't read the # correct?
I think this would solve it:
1- read each line of file until the end of it to get the number of cells rows which is n then take length of any String line to get number of columns which is m.
2- create boolean array cells[n][m].
3- read file line by line and put each line in String variable and iterate over the string variable characters if character is # put true in cells array otherwise put false.
String line="";
int n=0;
while(fileName.hasNextLine()){
line = fileName.nextLine();
n++;
}
int m = line.length();
boolean[][] cells = new boolean[n][m];
// initialize Scanner to read file again
Scanner in = new Scanner(new File("C:/Users/USER/Desktop/hashtag.txt"));
int i=0;
while(in.hasNextLine()){
line = in.nextLine();
for(int j=0; j < line.length(); j++){
char c = line.charAt(j);
if(c == '#'){
cells[i][j] = true;
}
else{
cells[i][j] = false;
}
}
i++;
}
You have many mistakes in code and this approach is definitely wrong, you don't even save values that you read from file inside array. Also this code is simply not how you do it, for reading files where you don't know length of file you want to use Lists where you don't need to specify number of elements that list will take(its possible to do get semi-working solution with arrays but there is no point of learning something that is simply wrong). Before even trying to work with files you should learn more basic things, you don't even initialize your arrays properly, you use string for size and index which is causing those issues you mentioned, another beginner mistake is trying to parse non-integer string to int(you are trying to convert ############ to int which is impossible, you can only use this if you know that string is an integer like 1 or 5 or 1000).
So my answer to your question is to just go slowly and learn basics then add new stuff step by step instead just rushing with it.
It says the [x] and [y] requires an int, but found a string. The same
issue is for cells[finalX][finalY] = true;
I tried parsing i.e. Integer.parseInt(x) however this gets me an
error: Exception in thread "main" java.lang.NumberFormatException: For
input string: "#####################"
One approach you could do is first read the entire file.
Example:
List<String> tempList = new ArrayList<>();
while (fileName.hasNextLine()) {
String line = fileName.nextLine();
tempList.add(line);
}
then you can do this:
boolean[][] cells = new boolean[tempList.size()][tempList.get(0).length()];
note - this solution assumes the length() of each line is the same and the columns of each line is the same.
Also, why do you need to perform this outside the loop?
cells[finalX][finalY] = true;
you should remove that line and let the loop do all the work to determine what's # or ' '. Also, your if condition doesn't seem to be doing the correct operation. Consider implementing this approach and then go on from there.

How to re-cast a java array

So i'm trying to read some user input which is then checked against two arrays of strings, then if the user input equals something in either of the arrays i want to put the user input into a new array, but when i go to print the new array which should contain the user input it prints that every value in the array is null
String[] VegiFruit = {"Apples", "Lettuce", "Broccoli"};
String[] Meats = {"Ground beef", "Hambuger"};
String[] Input = new String[20];
String[] InputGreen = new String[20];
String done = "done";
Scanner USER_IN = new Scanner(System.in);
Methods Use = new Methods(); //This is another class I have that just makes printing blank lines and borders look nicer
Use.border();
System.out.println("Enter Item name then follow instructions.");
Use.space();
for(int i = 0; i < 21; i++)
{
System.out.print(i+": ");
Input[i] = USER_IN.nextLine();
if(Arrays.asList(VegiFruit).contains(Input))
{
InputGreen[i] = Input[i];
System.out.println(InputGreen[i]); //Prints null for every value
}
}
So am I doing something wrong with the logic? or is it something else?
if(Arrays.asList(VegiFruit).contains(Input))
This line is totally wrong because you are comparing the object(Here Input is an parameter value of .contains method, it is an object) with a List of element, here element of the list is a String value.
So change the code like below,
if (Arrays.asList(VegiFruit).contains(Input[i])) {
InputGreen[i] = Input[i];
System.out.println(InputGreen[i]); //Now it is print the corresponding value.
}

excess spaces in front of printed text java

I am trying to write a program to reverse the letters/words in an inputted string, I thought I finally had it but I can't figure out why there are so many excess spaces in front of my output text. Any help would be greatly appreciated.
Also on a side note I attempted to make the scope of the array an incremented variable but it would not run, however I can use an incremented variable for the index position without any issues; why is that?
This is what I have so far and it seems to do exactly what I want it to do minus all the excess white space in front of the output.
Scanner in = new Scanner(System.in);
System.out.println("please enter string");
String strName = in.nextLine();
int ap = 0;
char strArray[] = new char[99];
for(int i=0;i < strName.length();i++)
{
strArray[ap] = strName.charAt(i);
ap++;
}
for (int e=strArray.length-1;e >= 0;e--)
{
System.out.print(strArray[e]);
}
Try this
Scanner in = new Scanner(System.in);
System.out.println("please enter string");
String strName = in.nextLine();
int ap = 0;
char strArray[] = new char[strName.length()];
for(int i=0;i < strName.length();i++)
{
strArray[ap] = strName.charAt(i);
ap++;
}
for (int e=strArray.length-1;e >= 0;e--)
{
System.out.print(strArray[e]);
}
The issue is you are initializing that char array to size 99. For a string of size 4... we have to print 95 nulls THEN the 4 chars in reverse order. This will be fixed by initializing the array to the actual size of the input string. No nulls to print then (printing nulls results in a white space).
Also on a side note I attempted to make the scope of the array an incremented variable but it
would not run, however I can use an incremented variable for the index position without any
issues; why is that?
Hmmm. Not sure what you mean? The word "scope" has specific meaning in CS that I don't think is the meaning you are referring to!

Why did I get an "ArrayIndexOutOfBoundsException"?

I'm pretty new to programming and working on an assignment for class. Now, I'm not asking for anyone to write my code for me but I'm stuck with a runtime error. In the assignment we need to read a file, use the first line, "15", to initialize the size of an array, and proceed to fill the array with the information from each line.
edit: I didn't want to post all of the code because I thought it would look too long but because of the downvotes for being vague, here it goes.
File:
15
produce,3554,broccoli,5.99,1
produce,3554,broccoli,5.99,1
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2335,windex,2.25,1 mini sprayer
cleaning,1342,wipes,3.99,10 units
cleaning,1342,wipes,3.99,10 units
produce,3546,lettuce,2.99,0.5
My Error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15
at Inventory.readFile(Inventory.java:45)
at Inventory.<init>(Inventory.java:12)
at Supermarket.main(Supermarket.java:3)
Class with the Line 45 in Question (line 45 is commented, scroll to the right)"
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Inventory{
Product[] list;
String[] invData;
private int i = 0;
public int count;
public Inventory (String f){
readFile(f);
}
public int indexOfProduct(int code){
for(i=0; i<list.length; i++){
if (list[i] != null)
if (list[i].getCode() == code)
return i;
}
return -1;
}
public Product delete(int pos){
Product temp = new Product();
temp = list[pos];
list[pos] = null;
return temp;
}
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine();
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]); // This is Line 45, Where the error occurs
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
public Product findCode(int c){
for(int i=0; i<list.length;i++)
if(list[1].getCode() == c)
return list[i];
return null;
}//end of method
}//end of class
Why did I get an "ArrayIndexOutOfBoundsException"? I hope someone can point out the flaw in my logic so I don't repeat it again.
Your issue is clearly with the use of i, as that is the only variable index on that line, and the out of range index is "15", which is just past the end of your 15-item array. So, couple of issues, all surrounding the use of i:
As nhellwig mentioned, be sure that i is actually initialized to 0 before calling this function.
Additionally, you're putting a lot of faith in the consistency of the item number in the file and the actual number of items. You should either produce a warning and stop trying to store items in the array if i >= itemCount, or use a container like an ArrayList that can grow to accommodate new items instead of a fixed size array.
Edit: Also, I should point out that you increment i whether you read an item or not, which means even blank lines will increment i, causing gaps in your list or array overruns. Since itemCount is the number if items, you should stick to that and only increment i if you read an actual item.
In that same spirit, you should verify that invData.length == 5 after you call split(), because a misplaced comma, etc. in your file may also end up with an OOB error. Granted, for your project, it's probably OK to make assumptions about the number of elements in a line that starts with "produce" or "cleaning", but in general it's important to be cautious with data coming from a user-created file.
I found the answer to be that I needed an "s.nextLine();"
Because I used "s.nextInt();" the pointer was just hangin around at the end of "15" in my file. Then, when the first line in the While loop "String line = s.nextLine();" executed the pointer moved from the end of 15 to before the p in produce in the 2nd line of the list file.
The working method looks like this:
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
s.nextLine(); // This is the new line that made it work
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine(); //moves file pointer over one
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]);
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
How many times do you call readFile? You should have i = 0; at the beginning of the function.
"i" should not be a global value but should be a method local variable, initialized to zero.

Finding the Length of a String within an ArrayList

I am writing a CSVParser program that seperates words at commas. I am currently trying to find and record the longest word that appears in the file. Here is my class.
import csv.CSVParser;
import java.io.*;
import java.util.*;
public class RecordFormatter {
public static void main (String[] args) {
CSVParser parser = new CSVParser(new File (args[0]));
while (parser.hasNextLine()) {
ArrayList<String> ls = parser.getNextLine();
for (int i = 0; i<ls.size(); i++) {
System.out.print("|" + ls.get(i) + " ");
}
System.out.print("|");
System.out.println();
}
CSVParser parser1 = new CSVParser(new File (args[0]));
ArrayList<Integer> maxCol = new ArrayList<Integer>();
while (parser1.hasNextLine()) {
ArrayList<String> ls1 = parser1.getNextLine();
for (int i = 0; i<ls1.size(); i++) {
maxCol.add(ls1.get(i)); //Here is where my bug occurs.
}
}
}
}
I have created two CSVParsers and am trying to use the second of the two to record the length. I tried (as you can see above) storing the int length value of each word into another Arraylist, but I can't seem to get it to work. Any help would be much appreciated.
Without giving the solution, since this is homework...
Notice that you are keeping every length value rather than comparing the current length against a previous value to determine if it is longer and only then keeping it.
Seems like you need just a single maxLength Integer (or int) rather than a list since you just want the longest single word.
If you wanted the longest word per line, a List might then be appropriate.
Another option would be to use a SortedList and get the largest value (last value) in the list.

Categories