when trying to read and create a file it cause Infinite loop - java

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)

Related

Java Scanner's nextLine() method gives no line found

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).

Java scanner reading null from my text file?

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.

Using increment to act as a column to add values into arraylist after splitting

I am using Java running on eclipse IDE .
I am trying to achieve a outcome of
Name: John
Money: 900
Password: john321
Name: Mark
Money: 300
Password: mark321
from a text file like this
//name|money|password
john|900|john321
mark|300|mark321
Here is what i tried:
public static void ReadFile() throws IOException {
FileReader rf = new FileReader("Data.dat");
BufferedReader br = new BufferedReader(rf);
String reader;
ArrayList<String> dataInfo = new ArrayList<String>();
while((reader = br.readLine())!=null)
{
dataInfo.add(reader);
} // end of while loop
br.close();
ArrayList<String> name = new ArrayList<String>();
ArrayList<String> money = new ArrayList<String>();
ArrayList<String> password = new ArrayList<String>();
for(int i =0; i<dataInfo.size();i++) {
String[] test = dataInfo.get(i).split("\\|");
int j =0;
for(String data : test) {
//System.out.println(data); // this print like what i wanted from the above outcome i posted
if(j==0){
name.add(data);
System.out.println(name); // This works well.
j++;
}
if(j==1){
password.add(data);
System.out.println(password); //ERROR this print the name instead
j++;
}
if(j==2){
money.add(data);
System.out.println(money); //ERROR this print the name instead
j++;
}
}
}//end of for-loop
for(int k =0;k<name.size();k++)
{
System.out.println("Name: " +name.get(k));
System.out.println("Money: " +money.get(k));
System.out.println("Password: " +password.get(k));
System.out.println("\n");
}
}
i am trying to make use of variable j to act as a column because further down the program i need to make use of the name,money,password for a filter search. i need the iteration on the for loop because i want to delete the whole text when users input the name of the user they wish to delete for e.g. if(name.get(i) = john) { //delete password.get(i) , money.get(i) } but the problem now is that the values i added into my arrayList is always the name only , where as System.out.println(data) prints everything.
You need else if statements as currently it will firstly do
if j == 0 then increment j
then it will do
if j == 1 - yes it is
Anyway a cleaner way (IMO) is to do
String[] test = dataInfo.get(i).split("\\|");
if (test.length == 3) {
just use test[0] test[1] and test[2]
}
else {
// otherwise this is bad data - need to do something special
}
If you really insists on use a construct like j then why bother using a for-each block, why not just use a traditional for loop
for (int j = 0; j < test.length; j++)
Also why do you use three ArrayList's
ArrayList<String> name = new ArrayList<String>();
ArrayList<String> money = new ArrayList<String>();
ArrayList<String> password = new ArrayList<String>();
It would make more sense to have one Object with three fields name, money password
and then to have an ArrayList of these Objects
ArrayList<MyObject> people = new ArrayList<MyObject>();
Your problem is, that your if blocks do absolutely nothing for the program flow. Every block is entered on every iteration, because the cases are not exclusive to each other.
You have to use else to ensure that only one block is entered per iteration.
for(String data : test) {
//System.out.println(data); // this print like what i wanted from the above outcome i posted
if(j==0){
name.add(data);
System.out.println(name); // This works well.
j++;
}
else if(j==1){
password.add(data);
System.out.println(password); //ERROR this print the name instead
j++;
}
else if(j==2){
money.add(data);
System.out.println(money); //ERROR this print the name instead
j++;
}
}
You have to re-arrange your if blocks as below:
if(j==2){
password.add(data);
System.out.println(password);
j++;
}
if(j==1){
money.add(data);
System.out.println(money);
j++;
}
if(j==0){
name.add(data);
System.out.println(name);
j++;
}
Other wise use if-else.
Your code shows ERROR because as you go to the first if block j==0
it changes value of j to 1. then it enters into second if block j==1.
But still variable data has value of name. data will have money and password only in next iteration of for(String data : test)
Note: Also I think j==1 will have money and j==2 will have password according to your text file. You have given it wrong in the if blocks.
You cann use java.util.Scanner to read file line by line. Split each line with | and add splitted values to correspondng lists:
ArrayList<String> name = new ArrayList<String>();
ArrayList<String> money = new ArrayList<String>();
ArrayList<String> password = new ArrayList<String>();
Scanner scanner = new Scanner(new File("filePath"));
while (scanner.hasNextLine()) {
String[] split = scanner.nextLine().split("\\|");
if(split.length==3) {
name.add(split[0]);
money.add(split[1]);
password.add(split[2]);
}
}
scanner.close();

A Java Scanner Exception

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;
}
}

Outputting a randomized array to a file

I'm trying to write a program that takes an array of 200 numbers (1-200), randomizes them, and then outputs those numbers to a text file.
I've been struggling for the whole day and I can't figure out why nothing is working.
Main method:
public static void main (String[] args)
{
int[] numbers= new int [201];
for (int i=0; i < numbers.length; i++)
{
numbers[i]=i;
}
}//end main method
Randomize method:
public static int[] randomizeArray(int[] numbers)
{
Random gen= new Random(10);
for (int i=0; i < numbers.length; i++)
{
int n= gen.nextInt(200);
numbers[i]=n;
}
return numbers;
}//end randomizeArray method
And the print method:
public static int[] outputArray(int[] numbers) throws IOException
{
FileOutputStream output;
output= new FileOutputStream("RandomOut.txt");
new PrintStream(output).println(randomizeArray(numbers));
output.close();
return numbers;
}//end method outputArray
Any help would be great, I know I'm overlooking something or doing something incorrectly.
Shouldn't you call outputArray at the end of your main method?
One of your problems is the line:
new PrintStream(output).println(randomizeArray(numbers));
This will probably print something like:
[I#10769dd
yes? You need to write a for loop to output the numbers, something like:
for (int i=0; i < numbers.length; i++) {
new PrintStream(output).println(numbers[i]);
}
except that you don't want to create the PrintStream each time in the loop.
Your main method initializes an array of 201 elements (instead of 200), and doesn't do anything with this array. So obviously, there is no randomization and now writing to any file. The main method should call randomizeArray and then outputArray.
The initialization of the array elements in main is useless, since the elements will be reinitialized by the randomizeArray method. This method, by the way, doesn't need to return anything.
Finally, the outputArray method should loop through the array and println each element. The stream should be closed in a finally block. It should not return anything either.
1) you need to use Arrays.toString(int[] arr) to print that array.
2) if you mean to reorder the array input, that requires code tht is very diferent.
otherwise, get rid of the input and use a new array.
3) call your helper methods!
EDIT: added this psuedocode:
boolean[] used=new boolean[200];
make old[] and new[]
for(i=0;i<200;i++){
int n=random number from 0 to 199;
while(used[n]) n=(n+1)%200;
new[i]=old[n];
used[n]=true;
}
return new;
Couldn't resist...
String filename = "random200.txt";
List<Integer> numbers = new ArrayList<Integer>();
for (int i = 1; i < 201; i++)
{
numbers.add(i);
}
StringBuilder sb = new StringBuilder();
while (!numbers.isEmpty())
{
int position = new SecureRandom().nextInt(numbers.size());
Integer randomNumber = numbers.remove(position);
sb.append(randomNumber + "\n");
}
try
{
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), "UTF8"));
out.append(sb.toString());
out.close();
}
catch (Exception ex)
{
throw new RuntimeException(ex);
}

Categories

Resources