使用 JFileChooser 和 JPasswordField 对 Vignere 密码进行故障排除

Troubleshooting Vignere Cipher using JFileChooser and JPasswordField

我正在尝试制作一个代码,它将使用 JFileChooser 和 JPassword 来获取加密代码或要加密的代码的输入。

这里是要加密的代码 "Be sure to drink your Ovaltine!" 保存在 .rtf 或 .txt 文件中。关键是"annie"。输出应该是

"Fv '$zi (# pzm"| (wy& `%ip(zzm%".

我在项目 "Password" 下有两个不同的 class 文件。一个class被称为"File Opener"。它调用 class "Password1".

这里是Password1.java.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;

/* PasswordDemo.java requires no other files. */

public class Password1 extends JPanel
                          implements ActionListener {
    private String key;
    private static String OK = "ok";

    private JFrame controllingFrame; //needed for dialogs
    private JPasswordField passwordField;

    public Password1(JFrame f) {
        //Use the default FlowLayout.
        controllingFrame = f;

        //Create everything.
        passwordField = new JPasswordField(10);
        passwordField.setActionCommand(OK);
        passwordField.addActionListener(this);

        JLabel label = new JLabel("Enter the key: ");
        label.setLabelFor(passwordField);

        JComponent buttonPane = createButtonPanel();

        //Lay out everything.
        JPanel textPane = new JPanel(new FlowLayout(FlowLayout.TRAILING));
        textPane.add(label);
        textPane.add(passwordField);

        add(textPane);
        add(buttonPane);
    }

    protected JComponent createButtonPanel() {
        JPanel p = new JPanel(new GridLayout(0,1));
        JButton okButton = new JButton("OK");
        okButton.setActionCommand(OK); 
        okButton.addActionListener(this);
        p.add(okButton);
        return p;
    }

    public void actionPerformed(ActionEvent e) {
        String cmd = e.getActionCommand();
        controllingFrame.dispose();

        if (OK.equals(cmd)) { //Process the password.
            char[] input = passwordField.getPassword();

            key = new String(input);
            //Zero out the possible password, for security.
            Arrays.fill(input,'0');
            passwordField.selectAll();
            resetFocus();
        } else {
            System.out.println("Please enter a key.");
        }
    }

    public String getKey(){
        return key;
    }

    //Must be called from the event dispatch thread.
    protected void resetFocus() {
        passwordField.requestFocusInWindow();
    }

    public static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("Key");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        final Password1 newContentPane = new Password1(frame);
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Make sure the focus goes to the right component
        //whenever the frame is initially given the focus.
        frame.addWindowListener(new WindowAdapter() {
            public void windowActivated(WindowEvent e) {
                newContentPane.resetFocus();
            }
        });

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event dispatch thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                //Turn off metal's use of bold fonts
        UIManager.put("swing.boldMetal", Boolean.FALSE);
        createAndShowGUI();
            }
        });
    }
}

这里是 FileOpener.java。

   import javax.swing.*;
import java.io.*;

import javax.swing.filechooser.*;
import java.awt.event.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Scanner;


public class FileOpener extends JPanel implements ActionListener {
    static private final String newline = "\n";
    private Password1 p1;
    JButton decodeButton, encodeButton;
    JFileChooser fc;
    JTextArea log;
    Scanner in = new Scanner(System.in);
    JFrame frame;
    File file;
    int count;

    public FileOpener(){
        // create and set up the window.
        frame = new JFrame("Open Your File");


        // make the program close when the window closes
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create the box layout
        frame.getContentPane( ).setLayout(new BoxLayout(frame.getContentPane( ), BoxLayout.Y_AXIS));

        //label prompting user for input
        JLabel label1 = new JLabel ("Would you like to encode or decode your file?", JLabel.CENTER);
        frame.getContentPane().add(label1);

        //create a filer chooser
        fc = new JFileChooser();

        // add a button object
        decodeButton = new JButton("Decode");
        decodeButton.addActionListener(this);
        frame.getContentPane( ).add(decodeButton);

        encodeButton = new JButton("Encode");
        encodeButton.addActionListener(this);
        frame.getContentPane( ).add(encodeButton);


        // display the window.
        frame.pack( );
        frame.setVisible(true);
    }
    public void actionPerformed(ActionEvent e) {

        //Handle open button action.
        if (e.getSource() == encodeButton) {
             frame.dispose();
            int returnVal = fc.showOpenDialog(FileOpener.this);

            if (returnVal == JFileChooser.APPROVE_OPTION ) {

                try {
                    file = fc.getSelectedFile();
                    p1 = new Password1(frame);
                    p1.createAndShowGUI();
                    //get length of key
                    String key = p1.getKey();
                    int length3 = key.length();
                    count = 0;
                    int keyAsciiValues[] = new int[length3];
                    String name1 ="";
                    //get ascii value of each letter in key
                    for (int k=0; k<length3; k++){
                        char a = key.charAt(k);
                        int ascii1 = (int)a;
                        //put ascii value of letter in key to array
                        keyAsciiValues[k]= ascii1;

                    }

                    FileInputStream file2= new FileInputStream(file);

                    //create a scanner for it
                    in = new Scanner(file2);
                    //read in message
                    String name;
                    name = in.nextLine();
                    for (int k=0; k<length3; k++){
                        char a = key.charAt(k);
                        int ascii1 = (int)a;
                        //put ascii value of letter in key to array
                        keyAsciiValues[k]= ascii1;
                    }
                    //measure length of code message array
                    int length1 = name.length();
                    //measures length of strings in code message array
                    for(int j=0;j<length1;j++){
                        char c = name.charAt(j);
                        int ascii = (int)c;
                        ascii += keyAsciiValues[count];
                        if(c != ' '){
                            count++;
                        }
                        if(count>length3-1){
                            count = 0;
                        }
                        while(ascii>126){
                            ascii-= 93;
                        }
                        char b=(char)ascii;
                        if(c == ' '){
                            b = ' ';
                        }
                        name1 += b;
                    }
                    System.out.println(name1);


                } catch (FileNotFoundException k){
                    //the file was not found!
                    System.out.println("File could not be opened!");
                }
            }

            //Handle save button action.
        } else if (e.getSource() == decodeButton) {
             frame.dispose();
            int returnVal = fc.showOpenDialog(FileOpener.this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {

                try {
                    file = fc.getSelectedFile();
                    p1 = new Password1(frame);
                    p1.createAndShowGUI();
                    //open the file

                    //get length of key 
                    String key = p1.getKey();
                    int length3 = key.length();
                    count = 0;
                    int keyAsciiValues[] = new int[length3];
                    String name1 ="";
                    //get ascii value of each letter in key
                    for (int k=0; k<length3; k++){
                        char a = key.charAt(k);
                        int ascii1 = (int)a;
                        //put ascii value of letter in key to array
                        keyAsciiValues[k]= ascii1;
                    }



                    //create a scanner for it
                    in = new Scanner(file);

                    //read in message
                    String name;
                    name = in.nextLine();
                    for (int k=0; k<length3; k++){
                        char a = key.charAt(k);
                        int ascii1 = (int)a;
                        //put ascii value of letter in key to array
                        keyAsciiValues[k]= ascii1;
                    }
                    //measure length of code message array
                    int length1 = name.length();
                    //measures length of strings in code message array
                    for(int j=0;j<length1;j++){
                        char c = name.charAt(j);
                        int ascii = (int)c;
                        ascii -= keyAsciiValues[count];
                        if(c != ' '){
                            count++;
                        }
                        if(count>length3-1){
                            count = 0;
                        }
                        while(ascii<33){
                            ascii+= 93;
                        }
                        char b=(char)ascii;
                        if(c == ' '){
                            b = ' ';
                        }
                        name1 += b;
                    }
                    System.out.print(name1);


                } catch (FileNotFoundException k){
                    //the file was not found!
                    System.out.println("File could not be opened!");
                }
            }

            in.close(); 

                log.append("Opening: " + file.getName() + "." + newline);
            }
    }


public static void main(String args[]) {
    //Schedule a job for the event dispatch thread:
    //creating and showing this application's GUI.
  FileOpener f = new FileOpener();
}    
}

在我添加 JFileChooser 和密码之前它工作正常,也就是代码的实际加密部分应该没有任何问题。

它在 FileOpener 的第 70 行给了我一个 java.lang.NullPointerException

int length3 = key.length();

谢谢!

createAndShowGUI() 方法中,您在 JFrame 中显示 Password1 实例,而不是模态 JDialog。因此,这个显示指令是非阻塞的,即它不会停止代码执行,也不会等到你点击一个按钮关闭 window.

因此,您在 actionPerformed() 方法可以执行和初始化 key 属性之前检索 Password1 实例 key,因此 key仍然是 null,当你调用它的任何方法时你会得到一个 NullPointerException

我的建议是在 createAndShowGUI() 中使用模态 JDialog 来管理您的 Password1 界面(使用 JPanel 进行初始化与您已经在使用JFrame)。这样,当您调用 createAndShowGUI() 时,FileOpener.actionPerformed() 方法执行将阻塞,直到您完成 Password1 对话框,因此您将确保 key 在您之前正确初始化在 FileOpener.actionPerformed().

中检索并使用它

最后一件事:小心frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);!在主 window 上使用它是可以的,但在任何辅助 window 上使用它会使整个程序在关闭后立即完全关闭。但无论如何,setDefaultCloseOperation()JDialog 版本不接受 EXIT_ON_CLOSE 作为有效参数,因此您将继续仅在主 FileOpener window 上使用它, 很好。