【问题标题】:Saving an object file when the frame is closed关闭框架时保存目标文件
【发布时间】:2014-06-06 03:50:00
【问题描述】:

所以我想做的是让程序在用户单击退出按钮时保存文件,以便下次我运行它时,所有第一次输入的用户仍然存在。每次我重新运行程序时,文件都是空的,就好像第一次运行从未发生过一样。我需要做什么才能保存文件?

所以这就是我现在所拥有的,但它只是保存第一次运行时的输入,并且在我运行它时从不添加新用户。我是不是把东西放错了地方或忘记了什么?

public class Admin extends JFrame  implements ActionListener{

static ArrayList<User> users = new ArrayList<User>();
static FileOutputStream fos;
FileInputStream fis;
static ObjectOutputStream oos;
ObjectInputStream ois;
JTextField realname = new JTextField("", 20);
JTextField username = new JTextField("", 20);
JTextField password = new JTextField("", 20);
JTextField repassword = new JTextField("", 20);
JLabel rnlabel = new JLabel("Real Name");
JLabel unlabel = new JLabel("Username");
JLabel pwlabel = new JLabel("Password");
JLabel rpwlabel = new JLabel("Rewrite Password");
String name;
String uname;
StringBuilder S = new StringBuilder("Registered Users\n");



//--------------------------------------------------------------------------
public static void main(String[] args) throws ClassNotFoundException,FileNotFoundException,IOException, NoSuchAlgorithmException {
try{
    Admin admin = new Admin();
}
catch (ClassNotFoundException e){ 
    System.err.println(" A ClassNotFoundException error was found in main."); 
    e.printStackTrace();
    }       
//catch (NoSuchAlgorithmException e){ System.err.println("SHA-1 algorithm not available"); System.exit(0);}
catch (FileNotFoundException e){
    System.err.println(" A FileNotFoundException error was found in main.");
    e.printStackTrace();
    }
catch (IOException e){
    System.err.println(" A IOException error was found in main.");
    }
}
//--------------------------------------------------------------------------
// Data members for the controller. 
//--------------------------------------------------------------------------
JTabbedPane tp = new JTabbedPane();

JButton quitButton = new JButton("Quit");

JPanel newCard = new JPanel(new BorderLayout());
JButton submitButton = new JButton("Submit");
JPanel buttonPanel1 = new JPanel( new GridLayout(6, 1));
JTextArea data = new JTextArea();
JScrollPane userPane = new JScrollPane( data );

//--------------------------------------------------------------------------
public Admin() throws IOException, ClassNotFoundException, FileNotFoundException {
    setBounds(200, 200, 800, 200);
    initComponents();
    submitButton.addActionListener(this);
    quitButton.addActionListener(this);
    setVisible(true);


}

//--------------------------------------------------------------------------
public void actionPerformed( ActionEvent e) {

    try (ObjectInputStream is = new ObjectInputStream(new FileInputStream("userfile.txt"))) {
        users = (ArrayList<User>) is.readObject();
        updateList();
    } catch (IOException | ClassNotFoundException exp) {
        exp.printStackTrace();
    }

    Object source = e.getSource();
    if (source == submitButton){
        name = realname.getText();
        uname = username.getText();
        getPassword();
        for (int i = 0; i < users.size(); i++){
            System.out.println(users.get(i).toString());
        }
        updateList();
    }

    if (source == quitButton) {
        try (ObjectOutputStream os = new ObjectOutputStream(
                new FileOutputStream("userfile.txt"))) {
            os.writeObject(users);
        } catch (IOException exp) {
            exp.printStackTrace();
        }
        System.exit(0);
    }
}

//----------------------------------------------------------------------------  
protected void updateList() {
    for (User object : users) {
        S.append(object + "\n");
    }
    String text = S.toString();
    data.setText(text);
}


//------------------------------------------------------------------------------    
private void getPassword() {

    String pw = password.getText().toString();
    String pword_check = repassword.getText().toString();
    if (pw.equals(pword_check)){
        users.add(new User(name, uname, pw));
        realname.setText("");
        username.setText("");
        password.setText("");
        repassword.setText("");
    }
    else{
        JOptionPane.showMessageDialog( null, 
                "Passwords do not match. Re-enter both of them.");
        password.setText("");
        repassword.setText("");
    }
}

//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
void initComponents(){
    //-- The New User Screen -----------------------------------------------
    JPanel rname = new JPanel( new GridLayout(1, 3));
    rname.setLayout( new GridLayout(1, 2));
    rname.add(realname);
    rname.add(rnlabel);

    JPanel uname = new JPanel( new GridLayout(1, 3));
    uname.setLayout( new GridLayout(1, 2));
    uname.add(username);
    uname.add(unlabel);

    JPanel npword = new JPanel( new GridLayout(1, 3));
    npword.setLayout( new GridLayout(1, 2));
    npword.add(password);
    npword.add(pwlabel);

    JPanel nrpword = new JPanel( new GridLayout(1, 3));
    nrpword.setLayout( new GridLayout(1, 2));
    nrpword.add(repassword);
    nrpword.add(rpwlabel);

    buttonPanel1.add(rname, BorderLayout.CENTER);
    buttonPanel1.add(uname, BorderLayout.CENTER);
    buttonPanel1.add(npword, BorderLayout.CENTER);
    buttonPanel1.add(nrpword, BorderLayout.CENTER);
    buttonPanel1.add(submitButton, BorderLayout.CENTER);
    buttonPanel1.add(quitButton, BorderLayout.CENTER);
    buttonPanel1.setPreferredSize(new Dimension(150, 10));
    newCard.add(buttonPanel1);
    userPane.setPreferredSize(new Dimension(350, 50));
    newCard.add(userPane, "East");


    //-------------------------------------------------------------------------
    tp.addTab( "New User", newCard);
    super.setTitle("Login System");
    Container pane = getContentPane();
    pane.add(tp, BorderLayout.CENTER);  
}

}

【问题讨论】:

  • 您在处理quitButton时正在读取对象?

标签: java swing serialization io


【解决方案1】:

你正在阅读quitButton上的文件内容

if (source == quitButton) {
    try {
        fis = new FileInputStream("userfile.txt");
        ois = new ObjectInputStream(fis);
        ois.readObject();
        ois.close();
    } catch (IOException | ClassNotFoundException ev) {
        ev.printStackTrace();
    }
    System.exit(0);
}

而不是写...

你可以尝试类似...

if (source == quitButton) {
    try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("userfile.txt"))) {
        os.writeObject(users);
    } catch (IOException exp) {
        exp.printStackTrace();
    }
    System.exit(0);
}

相反...

要重新读取内容,您只需执行类似...

try (ObjectInputStream is = new ObjectInputStream(new FileInputStream("userfile.txt"))) {
    users = (ArrayList<User>) is.readObject();
} catch (IOException exp) {
    exp.printStackTrace();
}

现在,因为JTextArea现在需要在两个地方更新,所以我创建了一个简单的方法...

protected void updateList() {
    for (User object : users) {
        S.append(object + "\n");
    }
    String text = S.toString();
    data.setText(text);
}

这只是用User 列表的当前内容更新JTextArea

这是我添加到加载代码中的...

try (ObjectInputStream is = new ObjectInputStream(new FileInputStream("userfile.txt"))) {
    users = (ArrayList<User>) is.readObject();
    updateList();
} catch (IOException exp) {
    exp.printStackTrace();
}

我把它放在你的类构造函数的末尾(以便首先初始化 UI)

正如 Braj 一直提到的,此代码来自您的 actionPerformed 方法(在两个 if 语句之后),这意味着它确实位于错误的位置。您希望执行此代码的唯一时间是列表已更改时,例如...

public void actionPerformed(ActionEvent e) {

    Object source = e.getSource();
    if (source == submitButton) {
        name = realname.getText();
        uname = username.getText();
        getPassword();
        for (int i = 0; i < users.size(); i++) {
            System.out.println(users.get(i).toString());
        }
        updateList();
    } else if (source == quitButton) {
        try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("userfile.txt"))) {
            os.writeObject(users);
        } catch (IOException exp) {
            exp.printStackTrace();
        }
        System.exit(0);
    }
}

现在,说了这么多,对象序列化不是长期存储数据的好选择,序列化意味着对象的短期存储,通常用于通过线路传输(但不限于)。

对于结构化数据,我更喜欢使用 XML,Java 有一个很好的 XML 绑定,请参阅Introduction to JAXB 了解更多详细信息。

这不是唯一的选择,请查看 How can I save the state of my program and then load it? 了解更详细的说明。

【讨论】:

  • System.exit(0);之后的任何代码都不应该在那里?
  • @Braj 它在if-else 语句中,从技术上讲,您可以出于其他原因在其他分支中执行代码...
  • 是的,这就是我指出这个东西的原因。 if 条件后面有一些代码。
  • @Braj 是的,但问题是,它做了什么,它更新了 JTextArea,这在技术上意味着它不属于那里......
  • 所以我添加了您告诉我的内容,但我不确定我是否将它们添加到正确的位置,因为它仍然没有保存任何其他用户。它只保存了我在第一次运行时输入的第一个用户。我用新代码编辑了我的问题。
【解决方案2】:

你应该在你的类中实现一个名为WindowListener 的接口。它允许您在窗口打开关闭等时执行代码。

【讨论】:

  • 所以我想做的是让程序在用户单击退出按钮时保存文件。你能帮忙解决这个问题而不是提供另一个处理程序吗?
  • @Braj 我对你的评论投了赞成票,然后我再次查看了“保存对象文件当框架关闭时”的标题”这将“按钮”置于不同的上下文中。如果指的是我在桌面应用程序上看到的小 x 按钮。在 Windows 中,我希望它会关闭。如果是 Java 应用程序。需要在应用程序上做事。关闭,WindowListener 是检测“关闭”状态的好方法。
【解决方案3】:

你所做的不是写东西!

在您的代码中:

if (source == quitButton) {
            try {
                fis = new FileInputStream("userfile.txt");
                ois = new ObjectInputStream(fis);
                ois.readObject();
                ois.close();
            } catch (IOException | ClassNotFoundException ev) {
                ev.printStackTrace();
            }
            System.exit(0);
        }

你只是读了一些东西,什么都不做,对吧?

【讨论】:

  • 实际上,如果您查看actionPerformed 的开头,OP实际上确实写入了文件的内容,但由于某种原因我不知道,而是在退出时读取文件,而不是在构建类时阅读它......
猜你喜欢
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-17
  • 2012-10-12
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多