I have wasted hours with this simple problem but I could not figure out why nextLine() cannot find the next line. Please help me, thank you!
I tried this code: https://www.geeksforgeeks.org/scanner-nextline-method-in-java-with-examples/ as an experiment and naturally it worked but my own will not.
Variable "test" is copied from the file.
Code portion:
ObservableList adatok;
#Override
public void initialize(URL url, ResourceBundle rb) {
int lines = 0;
try {
File f = new File("C:\\Users\\EDU_BYQN_0965\\Documents\\NetBeansProjects\\JSZ_SB\\src\\jsz_sb\\fokonyvi_kivonat.txt");
String test = "113,Vagyoni értékű jogok,3600,0,\n" +
"1173,Vagyoni értékű jogok értékhelyesbítése,360,0,\n" +
"1193,Vagyoni értékű jogok értékcsökkenése,0,2400,\n" +
"5,t,5,5,";
Scanner s = new Scanner(f);
while (s.hasNext() && s.nextLine() != null) lines++;
String[][] array = new String[lines][4];
String[] temporary = new String[4];
for (int i = 0; i < lines; i++) {
temporary = s.nextLine().split(",");
for (int j = 0; j < 4; j++) {
array[i][j]=temporary[j];
adatok = FXCollections.observableArrayList(
new TrialBalance(array[i][0], array[i][1], Integer.parseInt(array[i][2]), Integer.parseInt(array[i][3])));
}
}
} catch (FileNotFoundException ex) {
Logger.getLogger(FXML_scene2Controller.class.getName()).log(Level.SEVERE, null, ex);
}
Array "temporary" should contain the first line of the file, leastwise at the first loop and runtime error should not appear.
You exhaust the Scanner in this line:
while (s.hasNext() && s.nextLine() != null) lines++;
It stops because there are no more lines. (Note that the check hasNext() pairs with a call to next(), and hasNextLine() pairs with nextLine()).
So, if you try to read any more lines from the Scanner, there is nothing more to read.
You either need to create a new instance of the Scanner; or use a data structure that you don't need to know the size of a-priori, like a List (or resize your array as required; but there is little point in doing this "by hand" when ArrayList does that for you transparently).
Related
I'm writing some code to read an input file of book titles, and putting the read lines into an array and trying to print out the array. But when I try to print out the array, it just returns 'null' for each read line. I'm not sure what I'm doing wrong or what my code is doing. Any suggestions? Thanks!
Code:
import java.io.*;
import java.util.*;
public class LibraryInputandOutputs {
public static void main(String args[]) throws IOException{
int lineCount = 0;
File inputFile = new File("bookTitles.inp.txt");
Scanner reader = new Scanner(inputFile);
while(reader.hasNextLine()) {
reader.nextLine();
lineCount++;
}
String[] bookArray = new String[lineCount];
while (reader.hasNextLine()) {
for (int i = 0; i < lineCount; i++) {
bookArray[i] = reader.next();
}
}
for (int k = 0; k < lineCount; k++) {
System.out.println(bookArray[k]);
}
reader.close();
inputFile.close();
}
}
My text file I'm reading from is 20 book titles, all on different lines.
My output on the terminal is 20 lines of null.
Lets break this down:
This reads every line of the input file, counts each one, and then discards them:
while(reader.hasNextLine()) {
reader.nextLine();
lineCount++;
}
You are now at the end of file.
Allocate a string array that is large enough.
String[] bookArray = new String[lineCount];
Attempt to read more lines. The loop will terminate immediately because reader.hasNextLine() will return false. You are already at the end of file.
So you the statement assigning to bookArray[i] won't be executed.
while (reader.hasNextLine()) {
for (int i = 0; i < lineCount; i++) {
bookArray[i] = reader.next();
}
}
Since bookArray[i] = ... was never executed above, all of the array elements will still be null.
for (int k = 0; k < lineCount; k++) {
System.out.println(bookArray[k]);
}
One solution is to open and read the file twice.
Another solution is to "reset" the file back to the beginning. (A bit complicated.)
Another solution would be to use a List rather than an array so that you don't need to read the file twice.
Another solution is to search the javadocs for a method that will read all lines of a file / stream as an array of strings.
(Some of these may be precluded by the requirements of your exercise. You work it out ... )
The nested loop in step 3 is also wrong. You don't need a for loop inside a while loop. You need a single loop that "iterates" the over the lines and also increments the array index (i). They don't both need to be done by the loop statement itself. You could do one or the other (or both) in the loop body.
Stephen C has already pointed out the main problems with your logic. You're trying to loop twice through the file but you've already reached the end of the file the first time. Don't loop twice. "Merge" both the while loops into one, remove that for loop inside the while loop and collect all the book titles. You can then use the size of the list to print them later on. My Java might be rusty but here it goes -
import java.io.*;
import java.util.*;
public class LibraryInputandOutputs {
public static void main(String args[]) throws IOException {
// int lineCount = 0; - You don't need this.
File inputFile = new File("bookTitles.inp.txt");
Scanner reader = new Scanner(inputFile);
// Use an array list to collect book titles.
List<String> bookArray = new ArrayList<>();
// Loop through the file and add titles to the array list.
while(reader.hasNextLine()) {
bookArray.add(reader.nextLine());
// lineCount++; - not needed
}
// Not needed -
// while (reader.hasNextLine()) {
// for (int i = 0; i < lineCount; i++) {
// bookArray[i] = reader.next();
// }
// }
// Use the size method of the array list class to get the length of the list
// and use it for looping.
for (int k = 0; k < bookArray.size(); k++) {
System.out.println(bookArray[k]);
}
reader.close();
inputFile.close();
}
}
I agree with Stephen C. In particular, using a List is usually better than an array because it's more flexible. If you need an array, you can always use toArray() after the List is filled.
Are your book titles on separate lines? If so you might not need a Scanner class, and could use something like a BufferedReader or LineNumberReader.
The code below runs perfectly fine if the text file consists of lines of numbers but once it gets to for example a line that says "I am 40" it skips it instead of putting 40 into the array.
Scanner inFile = null;
File file = null;
String filePath = (JOptionPane.showInputDialog("Please enter a file path"));
int size = 0;
int[] result = new int[10];
try {
file = new File(filePath);
inFile = new Scanner(file);
int skippedCounter = 0;
for(int i = 0; inFile.hasNext(); i++){
if(inFile.hasNextInt())
result[i] = inFile.nextInt();
else{
String strOut = "";
String data = inFile.next();
for(int j = 0; j <= data.length() - 1; j++){
if(!Character.isLetter(data.charAt(j))){
strOut += data.charAt(j);
}
else
skippedCounter++;
}
result[i] = Integer.parseInt(strOut);
}
}
}
next() will give you the next token not the next Line. so variable i may go past ten. you would realize this if you didnt have an empty catch : that your array is going out of bounds
solution:
don't use a result array, use a result list, and append to its end whenever you have another result
note:
another hidden exception that could be occurring is when your parseInt fails due to non-numeric data. So don't wrap everything in a giant try/catch, it just makes it harder to debug!
I suggest you to use nextInt function just one time to keep the requested value, then use that variable whenever you need it. I think nextInt function moves to the next int each time you appeal it.
The following
result[i] = Integer.parseInt(strOut)
will result in a NumberFormatException when trying to process any letter. As strOut results in an empty String ""
You'll have to check for an empty String before attempting to parse
if (!strOut.isEmpty()) {
result[i] = Integer.parseInt(strOut);
}
This is my piece of code where I am trying to read from a file. My file currently has 4 lines but code is not coming out of the loop after reading those lines.
public void readPhoneBook() throws Exception {
try {
FileReader fileReader = new FileReader(file);
Scanner reader = new Scanner(file);
BufferedReader input = new BufferedReader(fileReader);
while (reader.hasNext()) {
String[] parts = reader.nextLine().split(" ");
if (parts.length == 4){
PhoneBook newPhone = new PhoneBook(parts[0],parts[1],parts[2],parts[3]);
entryList.add(newPhone);
}
fileReader.close();
reader.close();
for (int i=0; i < entryList.size(); ++i) {
entryList.add(new PhoneBook(entryList.get(i).getFirstName(), entryList.get(i).getLastName(),
entryList.get(i).getNumber(),entryList.get(i).getNote()));
System.out.println("2"+entryList.size());
}
}
} catch (Exception NoSuchElementException) {
}
}
The problem is that you are continually augmenting the list, of which the size controls the loop continuation itself:
for (int i=0; i < entryList.size(); ++i) {
...
entryList.add(new PhoneBook(entryList.get(i).getFirstName(),
entryList.get(i).getLastName(),
entryList.get(i).getNumber(), entryList.get(i).getNote()));
The statement entryList.add... is adding a value to the list, such that when the loop's condition is evaluated for the next iteration, entryList.size() will be bigger still.
You can fix it either by reading the size before the loop:
int entryListSize = entryList.size();
for (int i=0; i < entryListSize; ++i) {
Or, even better, by NOT adding values to the same list in the loop. In my opinion, this is the more sensible solution as it doesn't make much sense to add entries to the same list. Maybe you intended to add values to a different list object?
It is not entirely clear for me what the use is of the second loop is. Using Java 8 and streaming you could implement it as follows:
public List<PhoneBook> readPhoneBook(Path file) throws Exception {
return Files.lines(file)
.map(line -> reader.split(" "))
.filter(parts -> parts.length == 4)
.map(parts -> new PhoneBook(parts[0],parts[1],parts[2],parts[3])
.collect(Collectors.toList());
}
}
(the other answer explained the reason why it never stops)
I am trying to write a program where I take a textfile and copy it to another file. In this other file I want one word on the first line, two words on the second, three on the third and so on.
I am having some trouble with the Scanner class however. In the program below I keep getting a NoSuchElementException for line 14. I thought this was because I closed the Scanner in the while loop or something but even when I left out 'in.close()' I kept getting the same error.
Can anybody help me with this?
Thanks in advance.
import java.io.*;
import java.util.*;
public class WordPyramid {
public static void main(String[] args) throws FileNotFoundException {
File inputFile = new File(args[0]);
Scanner in = new Scanner(inputFile);
PrintWriter out = new PrintWriter(args[1]);
int s = 1;
int i = 0;
while (in.hasNext()) {
if (s >= i) {
for (i = 1; i <= s; i++) {
out.print(in.next());
out.print(" ");
}
out.println("");
s++;
}
}
in.close();
out.close();
}
}
A NoSuchElementException is thrown when there is no next() element. While you check to see if the file hasNext() at the start of each layer of the pyramid, you also need to check it before you call next() in the for loop. Your exception is thrown in the for loop because the next layer of the pyramid may require a larger number of words than remains in the file causing next() to try and get an element that is not there.
To fix it, wrap the interior of you for loop with if(in.hasNext()).
hasNext() checks if there is one more token in the scanner's stream. You are checking if there is one more token, and then assuming there are even more than one in your for loop. I would modify your for loop to look like this:
for (i = 1; i <= s && in.hasNext(); i++)
I would like to suggest that your loops are perhaps over-complicated.
Here is what I think is an easier answer, and avoids your exception:
File inputFile = new File(args[0]);
Scanner in = new Scanner(inputFile);
PrintWriter out = new PrintWriter(args[1]);
int s = 1;
int i = 0;
while (in.hasNext()) {
out.print(in.next() + " ");
i++;
if (i == s)
{
// Start the next line
out.println();
s++;
i = 0;
}
}
Hi all I wrote a mergesort program for a string array that reads in .txt files from the user. But what I want to do now is compare both files and print out the words in file one and not in file two for example apple is in file 1 but not file 2. I tried storing it in a string array again and then printing that out at the end but I just cant seem to implement it.
Here is what I have,
FileIO reader = new FileIO();
String words[] = reader.load("C:\\list1.txt");
String list[] = reader.load("C:\\list2.txt");
mergeSort(words);
mergeSort(list);
String x = null ;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length; j++)
{
if(!words[i].equals(list[j]))
{
x = words[i];
}
}
}
System.out.println(x);
Any help or suggestions would be appriciated!
If you want to check the words that are in the first array but do not exist in the second, you can do like this:
boolean notEqual = true;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length && notEqual; j++)
{
if(words[i].equals(list[j])) // If the word of file one exist
{ // file two we set notEqual to false
notEqual = false; // and we terminate the inner cycle
}
}
if(notEqual) // If the notEqual remained true
System.out.println(words[i]); // we print the the element of file one
// that do not exist in the second file
notEqual = true; // set variable to true to be used check
} // the other words of file one.
Basically, you take a word from the first file (string from the array) and check if there is a word in file two that is equal. If you find it, you set the control variable notEqual to false, thus getting out of the inner loop for and not print the word. Otherwise, if there is not any word on file two that match the word from file one, the control variable notEqual will be true. Hence, print the element outside the inner loop for.
You can replace the printing statement, for another one that store the unique word in an extra array, if you wish.
Another solution, although slower that the first one:
List <String> file1Words = Arrays.asList(words);
List <String> file2Words = Arrays.asList(list);
for(String s : file1Words)
if(!file2Words.contains(s))
System.out.println(s);
You convert your arrays to a List using the method Arrays.asList, and use the method contains to verify if the word of the first file is on the second file.
Why not just convert the Arrays to Sets? Then you can simply do
result = wordsSet.removeAll(listSet);
your result will contain all the words that do not exist in list2.txt
Also keep in mind that the set will remove duplicates ;)
you can also just go through the loop and add it when you reached list.length-1.
and if it matches you can break the whole stuff
FileIO reader = new FileIO();
String words[] = reader.load("C:\\list1.txt");
String list[] = reader.load("C:\\list2.txt");
mergeSort(words);
mergeSort(list);
//never ever null
String x = "" ;
for(int i = 0; i<words.length; i++)
{
for(int j = 0; j<list.length; j++)
{
if(words[i].equals(list[j]))
break;
if(j == list.length-1)
x += words[i] + " ";
}
}
System.out.println(x);
Here is a version (though it does not use sorting)
String[] file1 = {"word1", "word2", "word3", "word4"};
String[] file2 = {"word2", "word3"};
List<String> l1 = new ArrayList(Arrays.asList(file1));
List<String> l2 = Arrays.asList(file2);
l1.removeAll(l2);
System.out.println("Not in file2 " + l1);
it prints
Not in file2 [word1, word4]
This looks kind of close. What you're doing is for every string in words, you're comparing it to every word in list, so if you have even one string in list that's not in words, x is getting set.
What I'd suggest is changing if(!words[i].equals(list[j])) to if(words[i].equals(list[j])). So now you know that the string in words appears in list, so you don't need to display it. if you completely cycle through list without seeing the word, then you know you need to explain it. So something like this:
for(int i = 0; i<words.length; i++)
{
boolean wordFoundInList = false;
for(int j = 0; j<list.length; j++)
{
if(words[i].equals(list[j]))
{
wordFoundInList = true;
break;
}
}
if (!wordFoundInList) {
System.out.println(x);
}
}