【问题标题】:Java Hashtable saving into a fileJava Hashtable 保存到文件中
【发布时间】:2014-07-18 22:25:51
【问题描述】:

我写了这本日记,用户可以选择一个日期,为该日期写一些文本并保存它。 文本存储在每个日期的哈希表中。

我现在正在尝试将哈希表保存在文件中。 我对我写的代码有几个问题:

  1. 代码不工作,一些我不明白的错误:

线程“主”java.io.EOFException 中的异常

at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at Q2.MainPanel.updateHashFromFile(MainPanel.java:133)
at Q2.MainPanel.<init>(MainPanel.java:46)
at Q2.Main.main(Main.java:13)
  1. eclipse 总是警告我在我编写的处理文件的每个方法中添加 throws。你认为我的做法对吗?

  2. 是像我一样将 FileInputStream、ObjectInputStream、File 声明为全局参数的好方法吗?还是有更多推荐的方法?

  3. 你认为像我一样在同一个类中编写面板和 GUI 处理以及数据和保存处理的好方法吗?还是将它们分成几个类会更好?

这是代码:

package Q2;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class MainPanel extends JPanel{

    private String[] days = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};
    private String[] months = {"1","2","3","4","5","6","7","8","9","10","11","12"};
    private String[] years = {"2014","2015","2016","2017","2018"};
    private Font myFont = new Font("david", Font.BOLD, 24);
    JButton btnSave, btnShow;
    JComboBox daysBox,yearsBox,monthsBox;
    private static Hashtable<MyDate, String> diary;
    private JTextArea textArea;
    private static File file;
    private static FileInputStream in;
    private static FileOutputStream out;
    private static ObjectInputStream streamIn;
    private static ObjectOutputStream streamOut;

    //Constructor for main panel with BorderLayout with panels inside
    public MainPanel () throws IOException, ClassNotFoundException{
        this.setLayout(new BorderLayout());
        add(getDateButtons(),BorderLayout.NORTH);
        textArea = new JTextArea();
        textArea.setFont(myFont);
        add(textArea, BorderLayout.CENTER);
        add(getSaveShowButtons(),BorderLayout.SOUTH);

        file = new File("MyDiary");
        updateHashFromFile();


        diary = new Hashtable<MyDate, String>();
    }

    //create and return the NORTH date buttons panel
    private JPanel getDateButtons(){
        JPanel dateButtons = new JPanel();

        //create and add the days JCombobox
        daysBox = new JComboBox(days);
        daysBox.setFont(myFont);
        dateButtons.add(daysBox);

        //create and add the months JCombobox
        monthsBox = new JComboBox(months);
        monthsBox.setFont(myFont);
        dateButtons.add(monthsBox);

        //create and add the year JCombobox
        yearsBox = new JComboBox(years);
        yearsBox.setFont(myFont);
        dateButtons.add(yearsBox);

        return dateButtons;
    }

    //
    private JPanel getSaveShowButtons(){
        JPanel saveShowButtons = new JPanel();
        ButtonListener lis = new ButtonListener();

        btnSave = new JButton("save");
        btnSave.addActionListener(lis);
        btnSave.setFont(myFont);
        saveShowButtons.add(btnSave);

        btnShow = new JButton("show");
        btnShow.addActionListener(lis);
        btnShow.setFont(myFont);
        saveShowButtons.add(btnShow);

        return saveShowButtons;

    }

    private class ButtonListener implements ActionListener{


        @Override
        public void actionPerformed(ActionEvent e) {
            if (e.getSource()==btnSave){
                int day = Integer.parseInt((String)daysBox.getSelectedItem());
                int month = Integer.parseInt((String)monthsBox.getSelectedItem());
                int year = Integer.parseInt((String)yearsBox.getSelectedItem());
                MyDate date = new MyDate(day, month, year);
                System.out.println(date);
                diary.put(date,textArea.getText());
                textArea.setText(null);
                try {
                    updateHashToFile();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
            if (e.getSource()==btnShow){
                int day = Integer.parseInt((String)daysBox.getSelectedItem());
                int month = Integer.parseInt((String)monthsBox.getSelectedItem());
                int year = Integer.parseInt((String)yearsBox.getSelectedItem());
                MyDate date = new MyDate(day, month, year);
                String s = diary.get(date);
                if (s!=null)
                    textArea.setText(s+" ");
                else textArea.setText(" ");
            }

        }
    }

    @SuppressWarnings("unchecked")
    private static void updateHashFromFile() throws IOException, ClassNotFoundException{
        if(!file.exists())
            file.createNewFile();
        else {
            in = new FileInputStream(file);
            streamIn = new ObjectInputStream(in);
            diary = (Hashtable<MyDate, String>)streamIn.readObject();
        }

    }

    //update the file with the new hash table diary data
    private static void updateHashToFile() throws IOException{
        out = new FileOutputStream(file);
        streamOut = new ObjectOutputStream(out);
        streamOut.writeObject(diary);
    }
}

MyDate 类代码:

package Q2;

public class MyDate {

    private static int[] numOfDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //Number of days on each month
    private int day;
    private int month;
    private int year;

    //Constructor for date object
    public MyDate(int day, int month, int year){
        if(day<=numOfDays[month-1]){ //In case chosen day that not exist in the month the last day of the month will be chosen
            this.day = day;
        }else this.day = numOfDays[month-1];
        this.month = month;
        this.year = year;
    }

    //@override toString
    public String toString(){
        return this.day+"/"+ this.month+"/"+this.year;
    }

    //@override equals
    public boolean equals(Object other){
        if(this.day==((MyDate)other).day && this.month==((MyDate)other).month && this.year==((MyDate)other).year)
            return true;
        return false;
    }


    public int hashCode() {
        return ((day * 31) + month) * 31 + year; 
    }
}

主类代码:

package Q2;
import java.io.IOException;

import javax.swing.JFrame;

public class Main {

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        JFrame frame = new JFrame("Diary");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(700, 700);
        frame.setLocationRelativeTo(null);
        MainPanel mainPanel = new MainPanel();
        frame.add(mainPanel);

        frame.setVisible(true);
    }
}

【问题讨论】:

    标签: java file hashtable


    【解决方案1】:
    1. 我没有收到任何警告,但 ClassNotFoundException 异常看起来没用。

    2. 避免对流使用静态变量。您可以在此特定代码中本地声明它们,但这不是规则。相反,您可以将天、月和年声明为 static final,因为它们是常量并且永远不会改变。

    3. 这是您的选择,取决于代码最后的可读性。

    确保关闭蒸汽。

    这是修改后的代码以及我的建议。我暂时用 java.util.Date 替换了 MyDate 以便我可以编译代码,你可以忽略它。

    import java.awt.BorderLayout;
    import java.awt.Font;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.File;
    import java.io.FileInputStream;
    //import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.Hashtable;
    
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;
    
    public class MainPanel extends JPanel{
    
        private static final String[] days = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"};
        private static final String[] months = {"1","2","3","4","5","6","7","8","9","10","11","12"};
        private static final String[] years = {"2014","2015","2016","2017","2018"};
        private static final Font myFont = new Font("david", Font.BOLD, 24);
        JButton btnSave, btnShow;
        JComboBox daysBox,yearsBox,monthsBox;
        private Hashtable<java.util.Date, String> diary;
        private JTextArea textArea;
        private File file;
    
        //Constructor for main panel with BorderLayout with panels inside
        public MainPanel () throws IOException, ClassNotFoundException{
            this.setLayout(new BorderLayout());
            add(getDateButtons(),BorderLayout.NORTH);
            textArea = new JTextArea();
            textArea.setFont(myFont);
            add(textArea, BorderLayout.CENTER);
            add(getSaveShowButtons(),BorderLayout.SOUTH);
    
            file = new File("MyDiary");
            updateHashFromFile();
    
    
            diary = new Hashtable<java.util.Date, String>();
        }
    
        //create and return the NORTH date buttons panel
        private JPanel getDateButtons(){
            JPanel dateButtons = new JPanel();
    
            //create and add the days JCombobox
            daysBox = new JComboBox(days);
            daysBox.setFont(myFont);
            dateButtons.add(daysBox);
    
            //create and add the months JCombobox
            monthsBox = new JComboBox(months);
            monthsBox.setFont(myFont);
            dateButtons.add(monthsBox);
    
            //create and add the year JCombobox
            yearsBox = new JComboBox(years);
            yearsBox.setFont(myFont);
            dateButtons.add(yearsBox);
    
            return dateButtons;
        }
    
        //
        private JPanel getSaveShowButtons(){
            JPanel saveShowButtons = new JPanel();
            ButtonListener lis = new ButtonListener();
    
            btnSave = new JButton("save");
            btnSave.addActionListener(lis);
            btnSave.setFont(myFont);
            saveShowButtons.add(btnSave);
    
            btnShow = new JButton("show");
            btnShow.addActionListener(lis);
            btnShow.setFont(myFont);
            saveShowButtons.add(btnShow);
    
            return saveShowButtons;
    
        }
    
        private class ButtonListener implements ActionListener{
    
    
            @Override
            public void actionPerformed(ActionEvent e) {
                if (e.getSource()==btnSave){
                    int day = Integer.parseInt((String)daysBox.getSelectedItem());
                    int month = Integer.parseInt((String)monthsBox.getSelectedItem());
                    int year = Integer.parseInt((String)yearsBox.getSelectedItem());
                    java.util.Date date = new java.util.Date(day, month, year);
                    System.out.println(date);
                    diary.put(date,textArea.getText());
                    textArea.setText(null);
                    try {
                        updateHashToFile();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
                if (e.getSource()==btnShow){
                    int day = Integer.parseInt((String)daysBox.getSelectedItem());
                    int month = Integer.parseInt((String)monthsBox.getSelectedItem());
                    int year = Integer.parseInt((String)yearsBox.getSelectedItem());
                    java.util.Date date = new java.util.Date(day, month, year);
                    String s = diary.get(date);
                    if (s!=null)
                        textArea.setText(s+" ");
                    else textArea.setText(" ");
                }
    
            }
        }
    
        @SuppressWarnings("unchecked")
        private void updateHashFromFile() throws IOException, ClassNotFoundException{
            if(!file.exists())
                file.createNewFile();
            else {
                FileInputStream in = new FileInputStream(file);
                ObjectInputStream streamIn = new ObjectInputStream(in);
                diary = (Hashtable<java.util.Date, String>)streamIn.readObject();
                streamIn.close();
            }
    
        }
    
        //update the file with the new hash table diary data
        private void updateHashToFile() throws IOException{
            FileOutputStream out = new FileOutputStream(file);
            ObjectOutputStream streamOut = new ObjectOutputStream(out);
            streamOut.writeObject(diary);
            streamOut.close();
        }
    }
    

    【讨论】:

    • 谢谢!但是当我尝试编译它时,我得到:
    • 谢谢!但是当我尝试编译它时,我得到: java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source) at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source) 处的线程“main”java.io.EOFException 异常java.io.ObjectInputStream.readStreamHeader(Unknown Source) at java.io.ObjectInputStream.(Unknown Source) at Q2.MainPanel.updateHashFromFile(MainPanel.java:129) at Q2.MainPanel.(MainPanel.java :42) 在 Q2.Main.main(Main.java:13)
    • 即使在本地声明了流?
    猜你喜欢
    • 1970-01-01
    • 2010-12-28
    • 1970-01-01
    • 2020-08-23
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多