Нуждается в помощи JavaFX при записи в файл .txt

#java #javafx

#java #javafx

Вопрос:

Мне нужно создать проект JavaFX, который создает графический интерфейс для ввода имени и пароля. Я создал панели и подготовил почву. Элементы отображаются правильно, однако я не могу при нажатии кнопки получить информацию для записи в файл. Он создает файл, но не сохраняет данные. Мне нужно иметь возможность использовать несколько имен и паролей, чтобы я мог создать программу входа в систему reader для проверки текстового файла. Вот код, который у меня есть. Спасибо.

 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. Вы должны закрыть fw внутри блока try, а также catch-блока.

2. @dckuehn Хорошо, я попробовал это, и когда я открываю текстовый файл, я все еще не вижу введенную информацию.

3. извините, я прокомментировал, потому что это не был ответ. Это просто что-то лишнее, что я заметил. Вы всегда должны закрывать свои файлы / filewriters, и в вашем коде ваш файл не закрывается, если не возникает исключение.

4. Вы изменили код из исходного ответа, который технически работает, делая предоставленный ответ недействительным. Если вы собираетесь изменять код, добавьте обновления в виде отдельного блока, чтобы люди могли видеть прогресс

5. @MadProgrammer извините.

Ответ №1:

У вас «оригинального» fw.close метода был catch метод в try-catch блоке writeNewUser в вашем в вашем методе…

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

Как было указано, это будет вызвано только в том случае, если что-то пойдет не так. Кроме того, PrintWriter#close выдаст IOException и fw может быть null , вызывая больше проблем…

Модифицированный код лишь незначительно лучше…

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

Размещение close вызова внутри try раздела означает, что он будет вызван только в том случае, если все пойдет хорошо. Если по какой-либо причине возникает исключение, ресурс никогда не будет закрыт

Вы также должны закрывать внешний ресурс, BufferedWriter в данном случае это приведет к цепочке вызовов close для каждого заключающего ресурса.

Вместо этого вам следует использовать try-with-resources , который, например, автоматически закроет ресурсы…

 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();

    }
}
  

Взгляните на инструкцию try-with-resources для получения более подробной информации

Обновлено

Для добавления в файл вам может потребоваться вместо FileWriter использовать, например…

 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();

    }
}
  

Комментарии:

1. теперь это работает и добавляется в файл. Но я думаю, я думал, что с тем, как я писал код, что каждый раз, когда я ввожу пользователя, я могу очищать и добавлять больше пользователей. Он только заменяет существующего пользователя. Что я упускаю из виду, чтобы сделать это повторяемым?

2. Итак, это переопределяет содержимое, и вы хотите обновить файл?

3. Правильно, таким образом, если у меня есть 10 человек, которые вводят информацию, я могу получить и проверить. Я думал, что, поскольку это PrintWriter, это сделает это.

4. Как правило, средства записи файлов перезаписывают файлы, если не указано иное. Посмотрев на PrintWriter , я, кажется, не вижу, как это сделать. Вы могли бы рассмотреть возможность использования append вместо write или использовать FileWriter вместо, см. Обновления

Ответ №2:

Проблема заключается в методе writeNewUser:

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

fw.close() находится в цикле catch, но проблема в том, что он закрывается только при возникновении ошибки (вот почему существует блок catch)

Исправление для этого:

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

^^поместите fw.close() в блок try and catch.

Что касается возможности повторения, попробуйте сохранить пароли и имена пользователей (используя класс scanner) в массив перед инициализацией FileWriter, а затем выполните for цикл для перезаписи массива в файл.

Надеюсь, это поможет: Классический

Комментарии:

1. И если возникает исключение, ресурс никогда не закрывается… Лучше использовать try-with-resources

2. @JClassic даже с этим изменением он по-прежнему не записывает никаких данных в мой файл. Если я открою user.txt файл пустой?

3. @MadProgrammer Но вы никогда не инициализировали переменную fw вне блока try, поэтому вам не нужно закрывать ее при возникновении ошибки.

4. @planker1010 попробуйте использовать новый PrintWriter (новый файл(System.getProperty(«user.home») «Desktop», «users.txt «)) Это сохранит его на вашем рабочем столе

5. @JClassic вместо нового PrintWriter(«user.txt «)?

Ответ №3:

отсутствие bw.close() приводит к созданию пустого файла. это должно быть добавлено следующим образом:

 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());
        
        bw.close();  //missing this won't write anything into file
        fw.close();

    } catch (IOException e) {
        e.printStackTrace();
        fw.close();    
    }
}