问题
I'm writing a simple GUI program that uses log in information from a text file. It takes log in info from another GUI program that create's user accounts. I'm not sure how to easily serialize this effectively, as it's only something that I've learned recently. What should I do? How do I solve this serialization error, and what can I do to improve it and make it functional.
User class:
package passwordProgram;
import java.util.ArrayList;
import java.util.Arrays;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class User implements Serializable, ActionListener {
public static ArrayList<String> allUsernames = new ArrayList<String>();
String username;
String password;
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
User user = new User();
user.mainGUI();
}
JFrame frame;
JPanel panel;
JTextField createUsername;
JPasswordField createPassword;
JPasswordField confirmPassword;
JButton createAccount;
JLabel noValid;
public void mainGUI() {
noValid = new JLabel();
frame = new JFrame("Create a new account!");
panel = new JPanel();
panel.setBackground(Color.ORANGE);
createPassword = new JPasswordField(10);
confirmPassword = new JPasswordField(10);
createUsername = new JTextField(10);
JLabel userTxt = new JLabel("New Username: ");
JLabel userPass = new JLabel("New Password: ");
JLabel confirmPass = new JLabel("Confirm Password: ");
createAccount = new JButton("Create your account!");
panel.setLayout(new GridBagLayout());
GridBagConstraints left = new GridBagConstraints();
left.anchor = GridBagConstraints.WEST;
GridBagConstraints right = new GridBagConstraints();
right.anchor = GridBagConstraints.EAST;
right.weightx = 2.0;
right.fill = GridBagConstraints.HORIZONTAL;
right.gridwidth = GridBagConstraints.REMAINDER;
frame.getContentPane().add(BorderLayout.NORTH, noValid);
frame.getContentPane().add(BorderLayout.CENTER, panel);
panel.add(userTxt, left);
panel.add(createUsername, right);
panel.add(userPass, left);
panel.add(createPassword, right);
panel.add(confirmPass, left);
panel.add(confirmPassword, right);
frame.getContentPane().add(BorderLayout.SOUTH, createAccount);
frame.setVisible(true);
frame.setSize(500, 300);
createAccount.addActionListener(this);
}
public void actionPerformed(ActionEvent event) {
if (createUsername.getText().length() <= 0 ) {
noValid.setText("That is not a valid username. Please try again.");
frame.getContentPane().add(BorderLayout.NORTH, noValid);
}
else if (allUsernames.contains(createUsername.getText())) {
noValid.setText("That username is already taken. Please try again.");
frame.getContentPane().add(BorderLayout.NORTH, noValid);
}
else if (!(Arrays.equals(createPassword.getPassword(), confirmPassword.getPassword()))) {
noValid.setText("Your passwords do not match!");
frame.getContentPane().add(BorderLayout.NORTH, noValid);
} else {
SaveUser sUser = new SaveUser();
sUser.createAccount(this);
noValid.setText("Account created successfully");
frame.getContentPane().add(BorderLayout.NORTH, noValid);
}
}
}
SaveUser class(serialization)
package passwordProgram;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SaveUser implements Serializable{
public void createAccount(User u) {
try {
FileOutputStream fileOS = new FileOutputStream("userInfo.ser");
ObjectOutputStream objectOS = new ObjectOutputStream(fileOS);
objectOS.writeObject(u);
objectOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here's the error I get when I try and run the User class.
java.io.NotSerializableException: passwordProgram.User
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at passwordProgram.SaveUser.createAccount(SaveUser.java:12)
at passwordProgram.User.actionPerformed(User.java:104)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicRootPaneUI$Actions.actionPerformed(Unknown Source)
at javax.swing.SwingUtilities.notifyAction(Unknown Source)
at javax.swing.JComponent.processKeyBinding(Unknown Source)
at javax.swing.KeyboardManager.fireBinding(Unknown Source)
at javax.swing.KeyboardManager.fireKeyboardAction(Unknown Source)
at javax.swing.JComponent.processKeyBindingsForAllComponents(Unknown Source)
at javax.swing.JComponent.processKeyBindings(Unknown Source)
at javax.swing.JComponent.processKeyEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$000(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
And here's my log in class:
package passwordProgram;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class LogInScreen implements ActionListener {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e) {
}
LogInScreen logger = new LogInScreen();
logger.start();
}
回答1:
Personally, I think Object serialization is over kill in this situation.
You could simply write the details to a text file...
public TestFileIO() {
try {
writeUser(new File("User.inf"), "Test", "Password".toCharArray());
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void writeUser(File file, String name, char[] password) throws IOException {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file));
bw.write(name);
bw.newLine();
bw.write(password);
bw.flush();
} finally {
try {
bw.close();
} catch (Exception e) {
}
}
}
This will simply write the user name and password to a file, separating each by a new line.
If you need more then one user in the file, you could simple write the user name password on the same line, using a predefined delimiter...
public TestFileIO() {
try {
writeUser(new File("User.inf"), "Test", "Password".toCharArray());
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void writeUser(File file, String name, char[] password) throws IOException {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(file));
bw.write(name);
bw.write(";");
bw.write(password);
bw.flush();
} finally {
try {
bw.close();
} catch (Exception e) {
}
}
}
Now, if you worried about saving the password as plain text, you could (and personally world) save the password as a MD5 hash...
public TestFileIO() {
try {
writeUser(new File("User.inf"), "Test", "Password".toCharArray());
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void writeUser(File file, String name, char[] password) throws IOException, NoSuchAlgorithmException {
BufferedWriter bw = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = new byte[password.length];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) password[i];
}
md.update(bytes);
byte[] mdbytes = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < mdbytes.length; i++) {
sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1));
}
bw = new BufferedWriter(new FileWriter(file));
bw.write(name);
bw.newLine();
bw.write(sb.toString());
bw.flush();
} finally {
try {
bw.close();
} catch (Exception e) {
}
}
}
来源:https://stackoverflow.com/questions/16116168/how-do-i-solve-this-serialization-error-on-my-log-in-create-account-program