In need of JavaFX help writing to a .txt file


Question

I need to create a JavaFX project that creates a gui to input a name and password. I have created the panes, and set the stage. The items show correctly, however I cant upon button click get the info to write to the file. It creates the file but will not store the data. I need to be able to several names and passwords so I can create a reader login program to check the .txt file. Here is the code I have. Thanks.

import javax.swing.JOptionPane;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

import java.io.*;

public class AddUser extends Application {
    private TextField tfUsername = new TextField();
    private TextField tfPassword = new TextField();
    private Button btAddUser = new Button("Add User");
    private Button btClear = new Button("Clear");

    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) {
        // Create UI
        GridPane gridPane = new GridPane();
        gridPane.setHgap(5);
        gridPane.setVgap(5);
        gridPane.add(new Label("Username:"), 0, 0);
        gridPane.add(tfUsername, 1, 0);
        gridPane.add(new Label("Password:"), 0, 1);
        gridPane.add(tfPassword, 1, 1);
        gridPane.add(btAddUser, 1, 3);
        gridPane.add(btClear, 1, 3);

        // Set properties for UI
        gridPane.setAlignment(Pos.CENTER);
        tfUsername.setAlignment(Pos.BOTTOM_RIGHT);
        tfPassword.setAlignment(Pos.BOTTOM_RIGHT);

        GridPane.setHalignment(btAddUser, HPos.LEFT);
        GridPane.setHalignment(btClear, HPos.RIGHT);

        // Process events
        btAddUser.setOnAction(e -> writeNewUser());

        btClear.setOnAction(e -> {
            tfUsername.clear();
            tfPassword.clear();
        });   

        // Create a scene and place it in the stage
        Scene scene = new Scene(gridPane, 300, 150);
        primaryStage.setTitle("Add User"); // Set title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }

    public void writeNewUser() {      
        PrintWriter fw = null;

        try {
            fw = new PrintWriter("users.txt");
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(tfUsername.getText());
            bw.newLine();
            bw.write(tfPassword.getText());
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();

        }
    }

    /**
     * The main method is only needed for the IDE with limited
     * JavaFX support. Not needed for running from the command line.
     */
    public static void main(String[] args) {
        launch(args);
    }
}   
1
0
7/4/2014 1:45:59 AM

Accepted Answer

You're "original" had the fw.close method within the catch block of the try-catch in your writeNewUser method...

public void writeNewUser() {      
    PrintWriter fw = null;
    try {
        fw = new PrintWriter("users.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(tfUsername.getText());
        bw.newLine();
        bw.write(tfPassword.getText());
    } catch (IOException e) {
        e.printStackTrace();
        fw.close();
    }
}

As has been pointed out, this will only be called if something goes wrong. Also, PrintWriter#close will throw an IOException and fw could be null, causing more issues...

The modified code is only marginally better...

public void writeNewUser() {      
    PrintWriter fw = null;
    try {
        //....
        fw.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Placing the close call in within the try section means that it will only be called if all goes well. If an exception occurs for some reason, the resource will never be closed

You should also be closing the outer resource, the BufferedWriter in this case, this will chain the close call to each enclosing resource.

Instead, you should use a try-with-resources, which will close the resources automatically, for example...

public void writeNewUser() {
    try (BufferedWriter bw = new BufferedWriter(new PrintWriter("users.txt"))) {
        bw.write(tfUsername.getText());
        bw.newLine();
        bw.write(tfPassword.getText());
    } catch (IOException e) {
        e.printStackTrace();

    }
}

Take a look at The try-with-resources Statement for more details

Updated

To append to the file, you might need to use FileWriter instead, for example...

public void writeNewUser() {
    try (BufferedWriter bw = new BufferedWriter(new FileWriter("users.txt", true))) {
        bw.write(tfUsername.getText());
        bw.newLine();
        bw.write(tfPassword.getText());
        bw.newLine();
    } catch (IOException e) {
        e.printStackTrace();

    }
}
4
7/4/2014 2:10:23 AM

The problem is within the writeNewUser method:

public void writeNewUser() {

    PrintWriter fw = null;

    try {
        fw = new PrintWriter("users.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(tfUsername.getText());
        bw.newLine();
        bw.write(tfPassword.getText());
    } catch (IOException e) {
        e.printStackTrace();
        fw.close();    
    }
}

The fw.close() is in the catch loop, but the problem is that it only closes when there is an error (thats why there is a catch block)

The fix for this:

public void writeNewUser() {

    PrintWriter fw = null;

    try {
        fw = new PrintWriter("users.txt");
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(tfUsername.getText());
        bw.newLine();
        bw.write(tfPassword.getText());
        fw.close();
    } catch (IOException e) {
        e.printStackTrace();   
        fw.close 
    }
}

^^put the fw.close() in the try and catch block.

As for making it repeatable, try saving the passwords and usernames (Using the scanner class) into an array before initializing the FileWriter, and then have a for loop to rewrite the array into the file.

Hope this helps: Classic


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon