Search code examples
javaserializationhashtable

How to serialize and deserialize a Hashtable?


I am trying to Serialize and Deserialize a Hashtable but without success.

Here's the code:

Deserialize

    public static void read(File f) throws IOException, ClassNotFoundException
    {
        FileInputStream fos = new FileInputStream(f);
        ObjectInputStream oos = new ObjectInputStream(fos);

        list = new Hashtable<Date,String>((Hashtable<Date,String>)oos.readObject());
        oos.close();
    }

Serialize

    public static void write(String s) throws FileNotFoundException, IOException
    {
        FileOutputStream fos = new FileOutputStream(s);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(list);
    }

I wrote the Class Date, it's not Java's, but i did implemet Serializable there.

After I Deserialize the Hashtable and print it I am getting just {}.

What am I doing wrong?

EDIT

Main Class:

public class Main implements Serializable
{
    public static void main(String[] args) throws ClassNotFoundException, IOException
    {
        String[] options = {"Existing file","New file"};

        int choice = JOptionPane.showOptionDialog(null,
                "Whould you like to use an existing file or make a new file?",
                "Reminders", JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);

        System.out.println(choice);

        if(choice == 0)  //existing file
        {
            JFileChooser fc = new JFileChooser();

            try
            {
                Thread.sleep(1);
            }
            catch(InterruptedException ex)
            {
                Thread.currentThread().interrupt();
            }

            int returnVal = fc.showOpenDialog(null);

            GUI.read(fc.getSelectedFile());
        }
        else if(choice == 1) //new file
        {
            String name;
            do { name = JOptionPane.showInputDialog("Please enter the name of the new file: "); }
            while((name == null) || (name.length() == 0));

            GUI.write(name);
        }
        else if(choice == -1)
        {
            JOptionPane.showMessageDialog(null, "Good Bye!");
            System.exit(0);
        }

GUI Class:

public class GUI extends JPanel implements Serializable
{
    private DateGUI date;
    private JButton save;
    private static JTextArea text;
    private JScrollPane scroll;

    private static Hashtable<Date,String> list = new Hashtable<Date,String>;

    public static void read(File f) throws IOException, ClassNotFoundException
    {
        FileInputStream fos = new FileInputStream(f);
        ObjectInputStream oos = new ObjectInputStream(fos);

        list = ((Hashtable<Date,String>)oos.readObject());
        oos.close();
    }

    public static void write(String s) throws FileNotFoundException, IOException
    {
        FileOutputStream fos = new FileOutputStream(s);
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        oos.writeObject(list);
    }
    private class SaveListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent e) 
        {
            if(e.getSource() == save)
            {
                list.put(new Date(DateGUI.getDay(),DateGUI.getMonth(),DateGUI.getYear()), text.getText());
                text.setText("");
            }

        }
    }
}

Date Class: has 3 String fields of day,month,year. I did impelement Serializable and override equals and HashCode.

DateGUI Class: has GUI "stuff" and:

    public static String getDay()
    {
        return (String)day.getSelectedItem();
    }

    public static String getMonth()
    {
        return (String)month.getSelectedItem();
    }

    public static String getYear()
    {
        return (String)year.getSelectedItem();
    }

   private class ShowListener implements ActionListener
   {
       @Override
       public void actionPerformed(ActionEvent e) 
       {
           if(e.getSource() == show)
           {
               GUI.set(GUI.get(getDay(), getMonth(), getYear()));
           }
       }
   }

Solution

  • After I deserialize the Hashtable and print it I am getting just {}.

    What am I doing wrong?

    This code is copied from your MCVE code. You have since edited it out, but I am convinced that this or something like it was the real cause of your problem.

    public static void write(String s) throws FileNotFoundException, IOException
    {
        list = new Hashtable<Date,String>();
        FileOutputStream fos = new FileOutputStream(s);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
    
        oos.writeObject(list);
    }
    

    You should call close() on oos, but that's not the real problem.

    (The missing close() may cause the serialized file to be empty or incomplete / corrupt, but that would NOT lead to you reading back an empty Hashtable. You wold get an exception instead. Note that the new FileOutputStream(s) will truncate the file ...)

    The real problem is the first statement of the method. You are unconditionally assigning a new empty Hashtable to list. Then you are writing it. So (naturally) when you read back what you wrote to the file you will get an empty Hashtable again. That's what the {} you were seeing means.

    In short, your code is writing out an empty table and reading it back again. Hashtable serialization is working as it is supposed to work.