Java issues with Scanner and hasNextLine() while reading a file - java

I am having an issue with this unfinished program. I do not understand why this returns a "no Line found exception" when I run it. I have a while loop set up whose purpose is checking for this but I have done something wrong. I am trying to store information from a file into a 2d array for class.
import java.util.Scanner;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
import java.util.Arrays;
public class LabProgram {
public static void main(String[] args) throws IOException {
Scanner scnr = new Scanner(System.in);
int NUM_CHARACTERS = 26; // Maximum number of letters
int MAX_WORDS = 10; // Maximum number of synonyms per starting letter
String userWord = (scnr.next()) + ".txt"; //Get word user wants to search
char userChar = scnr.next().charAt(0); //Get char user wants to search
String[][] synonyms = new String[NUM_CHARACTERS][MAX_WORDS]; // Declare 2D array for all synonyms
String[] words = new String[MAX_WORDS]; // The words of each input line
File aFile = new File(userWord);
Scanner inFile = new Scanner(aFile);
while(inFile.hasNextLine()) {
for(int i = 0; i < synonyms.length; i++) {
words = inFile.nextLine().trim().split(" ");
for(int wordCount = 0; wordCount < words.length; wordCount++) {
synonyms[i][wordCount] = words[wordCount];
}
}
}
}
}

The issue is with this for loop:
for (int i = 0; i < synonyms.length; i++) {
words = inFile.nextLine().trim().split(" ");
....
}
You're iterating from i=0 upto synonym.length-1 times, but that file does not have these much lines, so, as soon as your file is out of lines but the for loop has scope to iterate more, the inFile.nextLine() gets no line and thus throw the exception.
I don't know what you are exactly doing here or want to achieve through this code, but this is what causing you the trouble.
Hope that answers your query.

Basically your problem is that you're only checking hasNextLine() before the for loop starts, and you're actually getting the next line on every iteration of the loop. So if you run out of lines while in the middle of your for loop an exception is thrown.
I'm actually not quite sure what your code is supposed to do but at the very least you need to add a hasNextLine() check every time before you actually run nextLine() to avoid errors like this.

Related

Why does one println statement change the entire output of my code?

Problem
I am currently creating a program to read a file and find a couple of variables. I am running into this problem where changing one println changes the entire output of my code. I have never run into this before and am not sure if this is an eclipse error or my error?
My Code
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class FileAnalyzer {
public static void main(String args[]) throws IOException {
Scanner input = new Scanner(System.in);
String fileName;
int words = 0, letters = 0, blanks = 0, digits = 0, miscChars = 0, lines = 0;
System.out.print("Please enter the file path of a .txt file: ");
fileName = input.nextLine();
File text = new File(fileName);
//System.out.println(text.exists());
Scanner word = new Scanner(text);
while(word.hasNext()) {
//System.out.println(word.next());
words++;
}
word.close();
Scanner letter = new Scanner(text);
while(letter.hasNext()) {
String currentWord = letter.next().toLowerCase();
for(int i = 0; i < currentWord.length(); i++) {
if(Character.isLetter(currentWord.charAt(i))) {
letters++;
}
}
}
letter.close();
Scanner blank = new Scanner(text);
while(blank.hasNextLine()) {
String currentWord = blank.nextLine();
for(int j = 0; j < currentWord.length(); j++) {
if (currentWord.charAt(j) == ' ') {
blanks++;
}
}
}
blank.close();
System.out.println("Words: " + words);
System.out.println("Letters: " + letters);
System.out.println("Blanks: " + blanks);
}
}
However
Simply changingSystem.out.println(word.next()) in the first Scanner instance changes the entire output. If i leave it in I get the three print statements at the bottom and what I am looking for. If I remove it since I do not want each word printed in the file it shows as nothing in the console. Not Sure why one print statement within a while statement changes the entire output.The only reason it was there in the first place was to make sure the scanner was taking input the way I had wanted.
Not Sure why one print statement within a while statement changes the entire output
Because when the statement is present, you're consuming a token from the scanner. When it's commented out, you're not. It's not the printing that consumes the token, it's the call to next().
With it commented out, your loop is:
while (word.hasNext()) {
words++;
}
hasNext() doesn't modify the state of the scanner, so that will just loop forever if it goes into the loop body at all.
If you want to have a line you can comment out or not, change the code to:
while (word.hasNext()) {
String next = word.next(); // Consume the word
System.out.println(next); // Comment this out if you want to
words++;
}
By using System.out.println(word.next()); you are cycling through the elements in a collection due to the next() method. So invoking next() directly will allow you to move through the iteration.
When commenting out //System.out.println(word.next());, then word.hasNext() will cause you to loop forever(provided there is a word) as you will not be able to move to the next token.
The below snippet will help you achieve your desired result
while(word.hasNext()){
word.next();
words++;
}
Not sure why you would want to go thru the text three times. But if you really have to, I would close the first scanner before opening the next.

Print Total Number of Different Words (case sensitive) from a file

**Edit after reviewing Tormod's answer and implementing his advice.
As the title states I'm attempting to print the total number of different words after receiving a file name from command line input. I receive the following message after attempting to compile the program:
Note: Project.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Here is my code. Any help is greatly appreciated:
import java.lang.*;
import java.util.*;
import java.io.*;
public class Project {
public static void main(String[] args) throws IOException {
File file = new File(args[0]);
Scanner s = new Scanner(file);
HashSet lib = new HashSet<>();
try (Scanner sc = new Scanner(new FileInputStream(file))) {
int count = 0;
while(sc.hasNext()) {
sc.next();
count++;
}
System.out.println("The total number of word in the file is: " + count);
}
while (s.hasNext()) {
String data = s.nextLine();
String[] pieces = data.split("\\s+");
for (int count = 0; count < pieces.length; count++)
{
if(!lib.contains(pieces[count])) {
lib.add(pieces[count]);
}
}
}
System.out.print(lib.size());
}
}
I would implement it using a HashSet Add all the words, and read out the size. If you want to make it case insensitive just manipulate all the words to uppercase or something like that. this uses some memory but...
one problem you got with the algorithm is that you do only have one "words". it only holds the words at the same line. so you only count same words at the same line.
HashSet stores strings by their hash value, and thus stores one word only one time.
construction: HashSet lib = new HashSet<>();
inside the loop: if(!lib.contains(word)){lib.add(word);}
check the word count: lib.size()
for(String s : words) {
if(s.equals(word))
count++;
}
You are comparing the words to an empty String, since it's a word it's always gonna be false.
Like Tormod said, the best would be to store the words in a HashSet, as it won't keep duplicates. Then just read out its size.

How to read in multiple arrays in one loop?

Here are my directions:
This program will use two arrays - these are called parallel arrays. You will NOT be using an array of objects.
You will have a minimum of 6 methods in this application (including main())
inputData() - input from the data file into two arrays - the data file is below, call it "population.txt"
remember to check for the existence of the file before associating the Scanner object to it
displayCountries() - display all of the countries - just the countries
Can you please tell me why this will not run? I need to have the value of the population and the country name together so I can write it in a table later. So I am thinking that I need to read the first value into countryName and the first value into populationNum instead of reading them all in at the same time. The text that I am reading in is below the code. I do not know how to do that though. I am also wondering if I need the [25] when I instantiate. It gives me this error:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at Population.inputData(Population.java:32)
at Population.main(Population.java:13)
This is my code:
import java.io.*;
import java.util.Scanner;
import java.io.IOException;
import java.text.DecimalFormat;
public class Population{
public static void main(String [] args)throws IOException{
//Arrays
String [] countryNames = new String [25];
int [] populationNum = new int [25];
//Input data from file into the array
inputData(countryNames, populationNum);
//Displays and calculations
displayCountries(countryNames);
} //end main()
//this class gets the input for arrays from the file
public static void inputData(String [] countryNames, int [] populationNum) throws IOException{
File infile = new File("population.txt.");
int index = 0;
Scanner scan = new Scanner(infile);
while(scan.hasNext())
for(int i = 0; i < countryNames.length; i++)
countryNames[i] = scan.nextLine();
for(int i = 0; i < populationNum.length; i++)
populationNum[i] = scan.nextInt();
} //end inputData()
//this class displays the countries
public static void displayCountries(String [] countryNames) {
for(int i = 0; i < countryNames.length; i++)
System.out.println(countryNames[i]);
} //end displayCountries()
}//end class
Ghana
24333000
Brazil
193364000
Australia
23480970
Nigeria
170123000
Papua New Guinea
6888000
Mexico
108396211
Egypt
79221000
Iran
75078000
Myanmar
50496000
Belgium
10827519
Tuvalu
10000
russia
141927297
You need to read into both arrays in the same loop, like this:
int i = 0;
while(scan.hasNext()) {
countryNames[i] = scan.nextLine();
if (scan.hasNext()) populationNum[i] = scan.nextInt();
if (scan.hasNext()) scan.nextLine(); // Go to the next line
i++;
}
The two for loops inside the while are incorrect (not to mention that the second for loop is not even part of the while, because you omitted curly braces).
Demo.
You need { after while(scan.hasNext()) and closing } after two for loops. What is happening is while loop scans all data then the for loops try to do scan.next when the scanner is already at end of file. Hope this helps

Java - Error: NoSuchElementException: No Line Found

I need to read strings from a file and store them in an array. However, my professor isn't allowing the class to use ArrayList. So I decided to run through the file once using hasNextLine() and counting how many lines there are then creating an array and making it equal to the amount of lines.
Then I made a while loop that is checking whether i is <= to the array, and giving the array[i] a value of fileInput.nextLine();. However, I seem to constantly get the error NoSuchElementException: No line found.
Here is my code:
public static void main(String[] args) throws FileNotFoundException {
int count = 0;
int i = 1;
//Read strings from a file and store in array
Scanner fileInput = new Scanner(new File("file.dat"));
while(fileInput.hasNextLine()) {
fileInput.nextLine();
count++;
}
String [] strArray = new String [count];
while (i <= strArray.length) {
/*Error Here*/ strArray[i] = fileInput.nextLine();
System.out.println(strArray[i]);
i++;
}
}
}
Would anyone know of a solution to my error?
P.S file.dat looks like this:
FRESH
MEAT
EVERY
SATURDAY
AT
TWELVE
Found the error. The problem ended up being that I need to create a new scanner class.
The Condition is wrong Here
while (i <= strArray.length)
You can write
while (i < strArray.length)
As you pointed out, the scanner cannot be reused. Since it reached the end of the file already.
Here is an alternative solution using standard Java 7 NIO:
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.Arrays;
public
class Reader
{
public static void main(String[] args) throws IOException
{
Path path = FileSystems.getDefault().getPath("file.dat");
Object[] myLines = Files.readAllLines(path, StandardCharsets.US_ASCII).toArray();
System.out.println(Arrays.toString(myLines));
}
}
As you know the index of an array in java starts with zero so the last elements index will always be lengthOfArray - 1
When you do this
while (i <= strArray.length)
Suppose your array contains 7 elements so the first element will be at zero index and it keep on adding the elements. Then a condition comes when i becomes 7 but still your while loop allows it because you have specified i <= strArray.length so it tries to add an element at seventh index but the last index of an array will always be lengthOfArray - 1 in this example it will be 6 so it cannot find the seventh index and will throw an exception.
To solve this just remove the equal sign
Scanner scannerForReading = new Scanner(new File("file.dat"));
while (i < strArray.length && scannerForReading.hasNextLine()) {
strArray[i] = scannerForReading.nextLine();
System.out.println(strArray[i]);
i++;
}

Java: How come I can't output my sorted values from a csv file?

I have a program that reads from a csv file full of peoples last names, first names, and birth years, assigns them into a special class array, and then gets sorted according to their last name. I believe that my code is working, so all I have to do to verify this is output the list and see if indeed all of the people were sorted by their last name. However, I am having trouble finding the right syntax to do this.
Here is the code of my Main.java, where I think the issue must be.
package project_1_sorting;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) throws IOException {
// open file input stream
BufferedReader reader = new BufferedReader(new FileReader(
"C:\\Users\\Owner\\Desktop\\Data 18k.csv")); // double check where this is trying to read it from
// read file line by line
String line = null;
Scanner scanner = null;
int index = 0;
Human[] pplArray = new Human[18000];
int i = 0;
while ((line = reader.readLine()) != null) {
Human ppl = new Human();
scanner = new Scanner(line);
scanner.useDelimiter(",");
while (scanner.hasNext()) {
String data = scanner.next();
if (index == 0)
ppl.setLastName(data);
else if (index == 1)
ppl.setFirstName(data);
else if (index == 2)
ppl.setBirthYear(data);
else
System.out.println("invalid data::" + data);
index++;
}
ppl.setKey(0); //change this for later things, you can use loop
ppl.setOrder(0); //change this to 1 if you want to invert the list of people
index = 0;
pplArray[i] = ppl;
i++;
System.out.println(pplArray);
}
//close reader
reader.close();
System.out.println(pplArray); // create
Selection_Sort selection = new Selection_Sort();
for (int j = 0; j < 18000; j++)
{
System.out.println(pplArray[j]);
}
}
}
So I was expecting this to output a giant list of all of my people from the csv file(ordered), with all of their info in the same format as they originally were, right. (one person per row, with 3 collumns for their 3 strings). However this is what I got instead:
run:
Test
17
true
0.142857
BUILD SUCCESSFUL (total time: 0 seconds)
I am not sure what the meaning of this is. It would seem that its doing something completely unrelated to what I am trying to do. This is the only project that I have open in NetBeans, so it must be generated from my functions, right? If anyone knows what this is all about, please let me know. If there is nothing else wrong with this Main.java, I can post my other .java files.
One thing I did notice was that, even when I commented out my selection sort function call, and all of the printline commands in this .java file, the same output was displayed on my screen.
Please let me know what you think.
You have a few issues
The statements
Selection_Sort selection = new Selection_Sort();
for (int i = 0; i < 18000; i++)
{
System.out.println(pplArray[i]);
}
should be in the main18k method rather than the class block
Then the variable i has already been used so you need to use a different variable name either of those places where its used
for (int j = 0; j < 18000; j++)
Lastly use main instead of main18k so the application has a valid entry point
You have not close the bracket properly.Also variable i is used twice in the main method.So change the variable name.
Remove bracket before line Selection_Sort selection = new Selection_Sort();
Change the variable i to j and code is as below :
for (int j = 0; j < 18000; j++)
{
System.out.println(pplArray[j]);
}

Categories

Resources