Creating, Writing and Reading the Same File returns an Array of 0s

Viewed 56

I am trying to create a file then write 10 random integers to the file. When trying to read those values into an array the result is all 0's instead of the actual values from the file. This only happens when the initial file creation and fileReader are referencing the same file. When I manually put another text file as an argument for fileReader the correct values are then read into the array. Please help me understand what is happening and how I can fix it.

    Random random = new Random();
    
    File file = new File("Hello.txt");
    FileWriter writer = new FileWriter(file);
    PrintWriter pw = new PrintWriter(writer);
    
    Scanner userInput = new Scanner(System.in);
    System.out.println("Enter # of Processes");
    int numProcesses = userInput.nextInt();
    userInput.close();
    for(int i=1; i <= numProcesses; i++) {
       pw.println(i);
       pw.println(random.nextInt(20)+1);
    }
    
    FileReader fr = new FileReader(file);
    int[] random_values = new int[numProcesses*2];
    int i=0;
    try {
        Scanner input = new Scanner(fr);
        while(input.hasNext()){
            random_values[i++] = input.nextInt();
        }
        input.close();
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    System.out.println(Arrays.toString(random_values));

    writer.close();

'''

1 Answers

Close after writing, before opening for reading

As commented by camickr, the direct answer to your Question is that you need to close the file before reading from it.

The data sent to that file may be buffered, not yet saved to storage. Closing the file flushes the buffer.

NIO2

Also, you are using an outmoded approach to file reading and writing in Java.

In modern Java we have NIO2 with Path, Paths, and Files (plural) classes found in the java.nio.file package. NIO2 provides for much simpler, shorter, clearer code. No need for the java.io.File, FileWriter, and PrintWriter classes.

See any of many tutorials such as this article. In particular, see File I/O (Featuring NIO.2) tutorial by Oracle, free-of-cost.

Prepare by specifying the limit of lines to be written. And specify the file name and folder location. Here we use the current working directory as our folder location. Call Paths.get (plural) to obtain a Path (singular) object.

final int limit = 7;
final Path path = Paths.get( "Hello.txt" );

Getting that Path object does not create the file in storage. We do not expect an existing file, so let's check for one. Call Files.exists.

if ( Files.exists( path ) ) throw new IllegalStateException( "File already exists. Exiting demo. Message # 4825beae-a188-40f6-a10d-134acf0e3908." );

If that passes, then we need to create our empty file. Call Files.createFile.

try { Files.createFile( path ); } catch ( final IOException e ) { e.printStackTrace(); }

Next we want to write our desired data into that file. Loop for our limit of lines. On each loop, get a random number. Make a line by appending a platform-specific end-of-line terminator.

To write that line into our file, simply call Files.writeString. This method opens and closes this file. That simplifies matters, eliminating the problem seen in your code with neglecting to close the file before reading. And this method makes for a nice simple line of code to do all the work. But re-opening the file on repeated lines is inefficient. So this approach is fine for small amount of data such as our example here. But for large amounts of data, learn to use an alternative approach.

for ( int i = 0 ; i < limit ; i++ )
{
    try
    {
        final int x = ThreadLocalRandom.current().nextInt( 20 );
        final String line = x + System.lineSeparator();
        Files.writeString( path , line , StandardOpenOption.APPEND );  
    }
    catch ( final IOException e )
    {
        e.printStackTrace();
    }
}

Now let's read that file.

We have a small file. So let's read all the data into memory at once, storing our lines in a List of String objects. Call Files.readAllLines. This method handles both opening and closing the file, so less chores for us.

As discussed above, this only works for small amounts of data. Large amounts of data may blow out the memory available to your JVM. For large data, learn about alternative approaches.

List < String > lines = null;
try { lines = Files.readAllLines( path ); } catch ( final IOException e ) { e.printStackTrace(); }

Dump to console.

System.out.println( "lines = " + lines );

When run.

lines = [11, 8, 9, 9, 8, 16, 3]

Our work is done. So let's delete that file we created. Call Files.delete.

try { Files.delete( path ); } catch ( final IOException e ) { e.printStackTrace(); }

Here is that entire example code in a single class.

package work.basil.demo.files;

import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class WriteAndReadDemo
{
    public static void main ( final String[] args )
    {
        // -------|  Prep  |-----------------------
        final int limit = 7;
        // Use `Paths` factory class to make a relative reference to a file in the current working directory.
        final Path path = Paths.get( "Hello.txt" );

        // -------|  Write file  |-----------------------
        // Verify the file does not exist.
        if ( Files.exists( path ) ) throw new IllegalStateException( "File already exists. Exiting demo. Message # 4825beae-a188-40f6-a10d-134acf0e3908." );
        // Obtaining the `Path` object does *not* create a new file. Use `Files.createFile` for that.
        try { Files.createFile( path ); } catch ( final IOException e ) { e.printStackTrace(); }

        for ( int i = 0 ; i < limit ; i++ )
        {
            try
            {
                final int x = ThreadLocalRandom.current().nextInt( 20 );
                final String line = x + System.lineSeparator();
                Files.writeString( path , line , StandardOpenOption.APPEND );  // Opens and closes file on each call, so not efficient for large amounts of data.
            }
            catch ( final IOException e )
            {
                e.printStackTrace();
            }
        }

        // -------|  Read file  |-----------------------
        List < String > lines = null;
        try { lines = Files.readAllLines( path ); } catch ( final IOException e ) { e.printStackTrace(); }
        System.out.println( "lines = " + lines );

        // -------|  Game over  |-----------------------
        // Ending our demo. So delete the file we created.
        try { Files.delete( path ); } catch ( final IOException e ) { e.printStackTrace(); }
    }
}
Related