Хороший способ хранить данные JTable на долгое время?

В моем текущем проекте я работаю с JTable а также DefaultTableModel, Пока все работает, и в настоящее время для сохранения TableModel я просто сериализую объект на диск.

Поскольку это может быть разумным способом сохранения и загрузки данных, мне не нравится тот факт, что данные полностью "запутаны" / в байтовой форме. Это делает данные практически невозможными для спасения, если происходит что-то плохое. Другая проблема - UUID сериализации, который усложняет обновление моей программы и не делает данные не загружаемыми.

База данных будет заполняться годами и будет содержать важную информацию. Чтобы восстановить данные, я хотел проанализировать TableModel в XML-файл, но это не удалось, потому что XML-кодировщик не может работать с JTable / TableModel.

Каковы рекомендации по сохранению данных из JTable в форме "открытого текста" эффективно? Является ли простой способ перебирать столбцы и строки и сохранять их в текстовом файле (с разделителями между данными столбцов) построчно? Мои опасения заключаются в том, что пользователь может использовать разделитель, такой как ":" (который я мог бы использовать), в качестве табличных данных и вызвать сбой анализатора.

Спасибо за вашу помощь.

2 ответа

Каковы рекомендации по сохранению данных из

API рекомендует XMLEncoder

Я хотел разобрать TableModel в XML-файл, но это не удалось, потому что XML-кодировщик не может работать с JTable / TableModel.

Вам необходимо создать собственный кодировщик. Ниже приведены две реализации для DefaultTableModel.

//  Following code is a more complete version of:
//  http://stackru.com/q/26250939/131872

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.table.*;

public class DefaultTableModelPersistenceDelegateTest
{
    private File file = new File("TableModel.xml");
    private final JTextArea textArea = new JTextArea();

    private final String[] columnNames = {"Column1", "Column2"};

    private final Object[][] data =
    {
        {"aaa", new Integer(1)},
        {"bbb\u2600", new Integer(2)}
    };

    private DefaultTableModel model = new DefaultTableModel(data, columnNames);
    private final JTable table = new JTable(model);

    public JComponent makeUI()
    {
        model.setColumnCount(5);
        JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        sp.setResizeWeight(.3);
        sp.setTopComponent(new JScrollPane(table));
        sp.setBottomComponent(new JScrollPane(textArea));

        JPanel p = new JPanel();
        p.add(new JButton(new AbstractAction("XMLEncoder")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    OutputStream os = new BufferedOutputStream(new FileOutputStream(file));
                    XMLEncoder xe = new XMLEncoder(os);
                    xe.setPersistenceDelegate(DefaultTableModel.class, new DefaultTableModelPersistenceDelegate());
                    xe.writeObject(model);
                    xe.close();

                    Reader r = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
                    textArea.read(r, null);
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }));

        p.add(new JButton(new AbstractAction("XMLDecoder")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    InputStream is = new BufferedInputStream( new FileInputStream( file ));
                    XMLDecoder xd = new XMLDecoder(is);
                    model = (DefaultTableModel)xd.readObject();
                    table.setModel(model);
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
            }
        }));

        p.add(new JButton(new AbstractAction("clear")
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                model = new DefaultTableModel();
                table.setModel(model);
            }
        }));

        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(sp);
        pnl.add(p, BorderLayout.SOUTH);
        return pnl;
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            @Override public void run()
            {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        f.getContentPane().add(new DefaultTableModelPersistenceDelegateTest().makeUI());
        f.setSize(420, 340);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

//  See following link for more information on Using XMLEncoder:
//  http://www.oracle.com/technetwork/java/persistence4-140124.html

class DefaultTableModelPersistenceDelegate extends DefaultPersistenceDelegate
{
    //  Initially creates an empty DefaultTableModel. The columns are created
    //  and finally each row of data is added to the model.

    @Override
    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder encoder)
    {
        DefaultTableModel model= (DefaultTableModel)oldInstance;

        //  Create XML to restore the column names

        Vector<String> columnNames = new Vector<String>(model.getColumnCount());

        for (int i = 0; i < model.getColumnCount(); i++)
        {
            columnNames.add( model.getColumnName(i) );
        }

        Object[] columnNamesData = new Object[] { columnNames };
        encoder.writeStatement(new Statement(oldInstance, "setColumnIdentifiers", columnNamesData));

        //  Create XML to restore row data

        Vector row = model.getDataVector();

        for (int i = 0; i < model.getRowCount(); i++)
        {
            Object[] rowData = new Object[] { row.get(i) };
            encoder.writeStatement(new Statement(oldInstance, "addRow", rowData));
        }
    }
}

class DefaultTableModelPersistenceDelegate2 extends DefaultPersistenceDelegate
{
    //  Initially creates a DefaultTableModel with rows and columns. Then the
    //  columns are reset and proper names are used. Finally data is set for each
    //  cell in the model.

    @Override
    protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder encoder)
    {
        super.initialize(type, oldInstance, newInstance, encoder);

        DefaultTableModel model= (DefaultTableModel)oldInstance;

        //  Create XML to restore the column names

        Vector<String> columnNames = new Vector<String>(model.getColumnCount());

        for (int i = 0; i < model.getColumnCount(); i++)
        {
            columnNames.add( model.getColumnName(i) );
        }

        Object[] columnNamesData = new Object[] { columnNames };
        encoder.writeStatement(new Statement(oldInstance, "setColumnIdentifiers", columnNamesData));

        //  Create XML to reset the value of every cell to its value

        for (int row = 0; row < model.getRowCount(); row++)
        {
            for (int col = 0; col < model.getColumnCount(); col++)
            {
                Object[] o = new Object[] {model.getValueAt(row, col), row, col};
                encoder.writeStatement(new Statement(oldInstance, "setValueAt", o));
            }
        }
    }
}

Вы должны использовать и сериализовать только модель, а не объекты GUI (из-за того, как вы это делаете, возможно, сериализация - не лучший вариант для вас). Если вы хотите хранить таблицу "заголовки" (макет JTable столбцы) для этой цели есть другая модель (+/- модель столбца таблицы - я без Java-среды).

РЕДАКТИРОВАТЬ: Если этот проект старый или важный, и вы думаете, стоит потратить время, то, возможно, вам следует переосмыслить свой класс модели?

Другие вопросы по тегам