drossy11
drossy11

Reputation: 89

Java input/output and Scanner object

Below are two functions in my class, I want to first read the number of lines from a text file, then store the contents in an array. The problem I am having is that if I do not comment out int aNumber = numOfObjects(newInput); the array does not get stored and printed, it's as if numOfObjects function got to the end of the text file, and I can no longer access it. If I comment it out it works fine. I tried adding a second Scanner object but it didn't help. What can I do to make it work?

public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){

        newInput = new Scanner(inputFile);
        forCapturing = new Scanner(inputFile);


        int aNumber = numOfObjects(newInput); 
        System.out.println(aNumber); 
        for(int i=0; forCapturing.hasNextLine(); i++){ 

            publicationArray[i] = new Publication();
            publicationArray[i].publication_code = forCapturing.nextLong();
            publicationArray[i].publication_name = forCapturing.next();
            publicationArray[i].publication_year = forCapturing.nextInt();
            publicationArray[i].publication_authorname = forCapturing.next();
            publicationArray[i].publication_cost = forCapturing.nextDouble();
            publicationArray[i].publication_nbpages = forCapturing.nextInt();
            System.out.println(publicationArray[i]);
            System.out.println("-----------------------------------\n");

        }
    }

private int numOfObjects(Scanner aScanner){ 
        int count = 0;
        while (aScanner.hasNextLine()){
            count++;
            aScanner.nextLine(); //if this isn't included you'll experience an infinite loop
        }
        System.out.println(count);
        return count;
    }
    } 

Upvotes: 0

Views: 164

Answers (4)

Milind Gokhale
Milind Gokhale

Reputation: 585

There is a way to do this as you want. i.e. by reading through the file 2 times. First to count and then to capture.

Just add below lines after your line int aNumber = numOfObjects(newInput); in correctListItems function.

public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){

    newInput = new Scanner(inputFile);


    int aNumber = numOfObjects(newInput); 
    newInput.close();
    inputFile.close();
    inputFile = new FileInputStream(
            new File(
                    "inputfile.txt"));
    System.out.println(aNumber); 
    forCapturing = new Scanner(inputFile);
    for(int i=0; forCapturing.hasNextLine(); i++){ 
    ....
    ....

So basically closing the scanner as well as file is important. And then creating the fileinputreader stream again will reset the file pointer to the beginning of the file. As you might already know, If the input file is not from the project folder, you have to give the complete path.

As a good process, its always better to close both the scanner object and file object after you're done, And then reinitialize the objects to start working on them again. Hope this helps.

Upvotes: 1

Kiong
Kiong

Reputation: 824

Well, I am not exactly sure but I can be quite certain that the FileInputStream object once the bytes has been read by Scanner once, the scanner will have a token to indicate that a particular line has been read.

How about you change your code to:

public void correctListItems(FileInputStream inputFile,FileOutputStream outputFile){

        forCapturing = new Scanner(inputFile);

        for(int i=0; forCapturing.hasNextLine(); i++){ 

            publicationArray[i] = new Publication();
            publicationArray[i].publication_code = forCapturing.nextLong();
            publicationArray[i].publication_name = forCapturing.next();
            publicationArray[i].publication_year = forCapturing.nextInt();
            publicationArray[i].publication_authorname = forCapturing.next();
            publicationArray[i].publication_cost = forCapturing.nextDouble();
            publicationArray[i].publication_nbpages = forCapturing.nextInt();
            System.out.println(publicationArray[i]);
            System.out.println("-----------------------------------\n");

        }
        System.out.println("Number of lines: "+ i);
    }

At least with this, you would not have to run 2 loops to the same set of data. better performance too and get the thing you need done in 1 round of a loop

Upvotes: 1

user2303720
user2303720

Reputation: 25

The scanner doesn't move to the next line unless you call nextLine. So the loop is infinite since you're always on the first line. But why do you need to know the number of objects in advance? Why not simply use a list instead of publicationArray?

Upvotes: 1

Mr M
Mr M

Reputation: 79

It looks like the scanner class uses an iterator internally. This means that it needs to be closed at some point, which I cant find in your code. Therefore I would (1) add following line to the numOfObects function before the return: “aScanner.close()”.
(2) I would create the second Scanner instance after you called the function, just to be sure. Hope it works.

Cheers!

Upvotes: 1

Related Questions