Losnikov
Losnikov

Reputation: 97

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()));
           }
       }
   }

Upvotes: 0

Views: 538

Answers (4)

Stephen C
Stephen C

Reputation: 719229

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.

Upvotes: 2

Qingfei Yuan
Qingfei Yuan

Reputation: 1212

I believe you should flush after writing.

oos.writeObject(list); oos.close();

Upvotes: 1

talha_norat
talha_norat

Reputation: 96

Are you even writing anything to the file, because the write method is taking in a String as a parameter, but you haven't specified which file you are writing to. Try:

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

    Hashtable<Date, String> list = new Hashtable<>();
    list.put(YourDateObject, "String");

    oos.writeObject(list);
}

Upvotes: 0

Daniil
Daniil

Reputation: 953

Here is code example:

public class Main {

/**
 * File name
 */
private final static String FILENAME = "test.bin";

/**
 * Entry point
 * 
 * @param args
 * @throws Exception 
 */
public static void main(String[] args) throws Exception {

    Hashtable<Date, String> original = new Hashtable<>();

    // write some data to hashtable
    for (int i = 0; i < 3; i ++) {
        original.put(new Date(), String.valueOf(i));
        TimeUnit.MILLISECONDS.sleep(100);
    }

    // serialize
    write(FILENAME, original);

    // deserialize
    Hashtable<Date, String> restored = read(FILENAME);

    // compare results
    System.out.println(restored);
    System.out.println(restored);
}

/**
 * Deserialization
 * 
 * @param filename
 * @return
 * @throws IOException
 * @throws ClassNotFoundException 
 */
public static Hashtable<Date, String> read(String filename) throws IOException, ClassNotFoundException {
    try (ObjectInputStream oos = new ObjectInputStream(new FileInputStream(filename))) {
        return (Hashtable<Date, String>) oos.readObject();
    }
}

/**
 * Serialization
 * 
 * @param filename
 * @param list
 * @throws FileNotFoundException
 * @throws IOException 
 */
public static void write(String filename, Hashtable<Date, String> list) throws FileNotFoundException, IOException {
    try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
        oos.writeObject(list);
    }
}

}

Upvotes: 0

Related Questions