Free for students · Ad-free · WCAG 2.1 AA Compliant · Accessibility

Using Text Files

Lesson ~12 min read 8 MCQs

In simple terms: In simple terms, using text files is about teaching your Java program how to read and use information stored in separate files, just like you'd read a grocery list or a list of high scores.

Why this matters

Imagine you've just spent hours building a game. Your friend, Priya, plays it and gets the highest score ever! You save her score in a variable. But then, you close the program. When you open it again... her score is gone. All the data stored in your program's memory vanishes the moment it stops running.

This is a huge problem for any real-world application, from video games to banking apps. We need a way to save data permanently. This is where files come in. A file is like a digital notebook for your program. It can write information down and, just as importantly, read it back later.

In this lesson, we'll focus on that second part: teaching your Java program how to open a text file, read the data inside it, and use that data to do something useful.

Program memory (RAM) is temporary, while files provide permanent storage.

Concept overview

flowchart TD
    A[Start] --> B{Create File object<br/>("data.txt")};
    B --> C{Create Scanner object<br/>(using File object)};
    C --> D{File exists?};
    D -- No --> E[Program throws<br/>FileNotFoundException];
    D -- Yes --> F{scanner.hasNext()?};
    F -- Yes --> G[Read data<br/>e.g., scanner.next()];
    G --> H[Process data];
    H --> F;
    F -- No --> I[scanner.close()];
    I --> J[End];
This diagram shows a flowchart for reading a text file in Java. It starts by creating a File object, then a Scanner object. A decision point checks if the file exists; if not, it leads to an exception. If it exists, the flow enters a loop that checks if the scanner has more data. If true, it reads and processes the data, then loops back. If false, it closes the scanner and ends the process.

Core explanation

Why Files? The Whiteboard vs. The Notebook

Think of your program's memory (the RAM) as a giant whiteboard. While the program is running, you can write on it, erase things, and read what's there. It's fast and useful. But as soon as the power is cut—as soon as your program ends—an eraser wipes the entire board clean.

A file is like a notebook. The information you write in it stays there, even after you put the notebook away. This is called persistence. When your program needs to remember something for later, like a high score, a user's saved game, or a list of contacts, it writes that data to a file.

Our focus today is on reading data that's already in a file.

The Three Key Players for Reading Files

To read a file in Java, you need to know about three things from the java.io package:

The key Java classes involved in reading text files.
  1. File: This object doesn't hold the file's data. Instead, it represents the file itself. Think of it as a signpost that has the name and location of the file, like "scores.txt".
  2. Scanner: This is the real workhorse. You give a Scanner a File object, and it does the actual reading. It has methods to grab numbers, words, or entire lines from the file.
  3. IOException: This is an "exception," or a type of error. What if you try to read a file named "scores.txt" but it doesn't exist? Your program would crash. Java requires you to plan for this possibility. IOException stands for "Input/Output Exception," and it's the error that gets thrown when file operations go wrong.

Setting Up Your Program to Read a File

Let's look at the basic structure. Imagine we have a file named data.txt.

First, you need to import the necessary classes at the top of your Java file.

import java.io.File;         // For the File class
import java.io.IOException;    // For the error handling
import java.util.Scanner;      // For the Scanner class

Next, in any method that is going to handle files, you must tell Java you're prepared for a file-related error. You do this by adding throws IOException to the method signature.

public static void main(String[] args) throws IOException {
    // Our file-reading code will go here
}

This is where a lot of students slip up. They forget throws IOException and their code won't even compile. Think of it as a required safety warning, like "Caution: Contents May Be Hot." You're telling Java, "I know a file might not be found, and I'm prepared for that possibility." For now, it just means the program will stop if the file is missing.

Always declare `throws IOException` when performing file operations.

Opening and Reading the File

Inside your method, you'll create the File and Scanner objects.

// 1. Create a File object that points to your file.
File dataFile = new File("data.txt");

// 2. Create a Scanner that uses the File object.
Scanner fileScanner = new Scanner(dataFile);

Now fileScanner is connected to data.txt and ready to read! But how do we read everything if we don't know how long the file is? We use a while loop with the hasNext() method.

The hasNext() method is like asking the Scanner, "Is there anything left to read?" It returns true if there is, and false if you've reached the end of the file.

// 3. Loop as long as the file has more content.
while (fileScanner.hasNext()) {
    // Read and process the data inside the loop
    String word = fileScanner.next();
    System.out.println(word);
}

The Scanner's Toolbox

The Scanner has different methods depending on what kind of data you expect to read.

  • next(): Reads the next "token" (a sequence of characters separated by spaces) as a String.
  • nextInt(): Reads the next token and tries to convert it to an int.
  • nextDouble(): Reads the next token and tries to convert it to a double.
  • nextLine(): Reads all remaining characters on the current line, including spaces, until it hits the newline character (from pressing Enter).

The nextLine() Trap: A Critical Warning

This is one of the most common and frustrating bugs you'll encounter.

Imagine a file player.txt:

Aaliyah
95.5
12

You write this code:

// Reads the name "Aaliyah"
String name = fileScanner.nextLine();

// Reads the score 95.5
double score = fileScanner.nextDouble();

// Reads the level 12
int level = fileScanner.nextInt();

This seems fine. But what if the file was formatted differently?

player_info.txt:

12 95.5
Aaliyah Johnson

And you try to read it like this:

int level = fileScanner.nextInt(); // Reads 12
double score = fileScanner.nextDouble(); // Reads 95.5
String name = fileScanner.nextLine(); // Tries to read "Aaliyah Johnson"

The name variable will be an empty string! Why?

When fileScanner.nextDouble() reads 95.5, it leaves the newline character (the invisible "Enter" key press) in the input stream. When fileScanner.nextLine() is called, it sees that leftover newline character immediately and thinks, "Ah, an empty line!" and stops reading.

The fix: After you read a number with nextInt() or nextDouble(), if you plan to read a whole line next with nextLine(), you must add an extra fileScanner.nextLine(); to consume the leftover newline character.

int level = fileScanner.nextInt();
double score = fileScanner.nextDouble();
fileScanner.nextLine(); // <-- The crucial fix! Consumes the leftover newline.
String name = fileScanner.nextLine(); // Now this works correctly.

Splitting Lines for Complex Data

What if a single line in your file contains multiple pieces of information, separated by commas? This is a very common format, called CSV (Comma-Separated Values).

teams.txt:

Red Sox,Boston,92
Yankees,New York,99

Reading this with next() would be messy. A better way is to read the entire line with nextLine() and then use the String.split() method.

split(del) takes a "delimiter" (the character you want to split by) and returns a String array.

while (fileScanner.hasNextLine()) {
    String line = fileScanner.nextLine(); // "Red Sox,Boston,92"
    String[] parts = line.split(","); // parts is now ["Red Sox", "Boston", "92"]

    String teamName = parts[0];
    String city = parts[1];
    int wins = Integer.parseInt(parts[2]); // Don't forget to parse numbers!

    System.out.println(teamName + " from " + city + " had " + wins + " wins.");
}

Don't Forget to Clean Up!

Once your while loop is finished and you're done with the file, you must close the scanner. This releases the file from your program's control. It's good practice and prevents potential issues.

// After the loop...
fileScanner.close(); // 4. Close the scanner to release the file.
System.out.println("File reading complete.");

Think of it as closing a book and putting it back on the shelf.

See it in action

python
Line 1
Output
Click Run to see the output.

        
Try these
    © Shrutam.ai

    Worked examples

    Example 1

    Calculating the Average Score

    Let's say we have a file named scores.txt containing a list of exam scores.

    scores.txt:

    88.5
    92
    76.5
    100
    83

    Problem: Write a program to read all the scores from scores.txt, calculate their average, and print the result.

    Solution Walkthrough:

    1. 1
      Setup
      We need to import File, IOException, and Scanner. Our main method must include throws IOException.
    2. 2
      Initialization
      We'll create File and Scanner objects. We also need variables to keep track of the total sum and the count of scores.
    3. 3
      The Loop
      We'll use a while loop with fileScanner.hasNextDouble() to make sure we only read double values. Inside the loop, we'll read each score using fileScanner.nextDouble(), add it to our sum, and increment our count.
    4. 4
      Calculation &amp; Cleanup
      After the loop finishes, we'll calculate the average (sum / count). Finally, we'll close the scanner and print the result.

    Code:

    import java.io.File;
    import java.io.IOException;
    import java.util.Scanner;
    
    public class ScoreCalculator {
        public static void main(String[] args) throws IOException {
            File scoreFile = new File("scores.txt");
            Scanner fileScanner = new Scanner(scoreFile);
    
            double sum = 0.0;
            int count = 0;
    
            while (fileScanner.hasNextDouble()) {
                double score = fileScanner.nextDouble();
                sum += score;
                count++;
            }
    
            fileScanner.close(); // Close the scanner!
    
            if (count > 0) {
                double average = sum / count;
                System.out.printf("The average score is: %.2f\n", average);
            } else {
                System.out.println("No scores found in the file.");
            }
        }
    }

    Example 2: Processing a Roster with split()

    Now for a more complex file, roster.csv, containing player data.

    roster.csv:

    Carlos,Rodon,10
    Jordan,Montgomery,52
    Marcus,Stroman,0

    Problem: Read the roster, and for each player, print their full name and jersey number in a user-friendly format.

    Solution Walkthrough:

    1. 1
      Setup
      Same as before, with throws IOException.
    2. 2
      The Loop
      Since each line is a complete record, we'll use while (fileScanner.hasNextLine()). This is better than hasNext() because we want to process the data line by line.
    3. 3
      Read and Split
      Inside the loop, we'll read the entire line into a String variable using fileScanner.nextLine(). Then, we'll use line.split(",") to break the line into a String array.
    4. 4
      Process and Print
      We'll access the parts of the array (parts[0], parts[1], parts[2]) to get the first name, last name, and number. Then we'll print a formatted string.
    5. 5
      Cleanup
      Close the scanner after the loop.

    Code:

    import java.io.File;
    import java.io.IOException;
    import java.util.Scanner;
    
    public class RosterReader {
        public static void main(String[] args) throws IOException {
            File rosterFile = new File("roster.csv");
            Scanner fileScanner = new Scanner(rosterFile);
    
            System.out.println("Team Roster:");
            while (fileScanner.hasNextLine()) {
                String line = fileScanner.nextLine();
                String[] parts = line.split(",");
    
                String firstName = parts[0];
                String lastName = parts[1];
                String number = parts[2]; // It's a String!
    
                System.out.println("- #" + number + " " + firstName + " " + lastName);
            }
    
            fileScanner.close();
        }
    }
    Tracing the `ScoreCalculator` as it reads `scores.txt`.

    Try it yourself

    Ready to try it yourself? Create the text files described below and write the Java code to solve the problems.

    1. City Filter

    Create a file named cities.txt with the following content:

    Seattle
    Boston
    San Diego
    Chicago
    Atlanta
    Santa Fe

    Write a program that reads cities.txt and prints only the cities that start with the letter "S".


    2. Student Averages

    Create a file named grades.txt with student names and three test scores, separated by commas.

    Liam Smith,85,90,95
    Sofia Garcia,100,92,94
    Maya Patel,78,82,80

    Write a program that reads grades.txt, and for each student, calculates and prints their name and average test score.

    Flowchart for filtering cities that start with 'S'.
    Converting String parts to integers for calculations.