简体   繁体   English

长期存储JTable数据的好方法?

[英]Good way to store JTable data for longterm?

in my current project I am working with a JTable and DefaultTableModel . 在当前项目中,我正在使用JTableDefaultTableModel Everything is working so far and currently for saving the TableModel I simply serialize the object to disk. 到目前为止,一切工作正常,并且当前用于保存TableModel,我只是将对象序列化到磁盘上。

As this might be a reasonable way of saving and loading the data I don't like the fact that the data is completely "obfuscated" / in byte form. 因为这可能是保存和加载数据的一种合理方法,所以我不喜欢数据完全以字节形式“模糊处理”。 This makes data almost impossible to rescue if something bad happens. 如果发生不良情况,这几乎使数据无法挽救。 Another problem is the serialization UUID which makes it harder to update my program and don't make the data un-loadable. 另一个问题是序列化UUID ,这使得更新程序变得更加困难,并且不会使数据不可卸载。

The database will be filled over the years and will contain important information. 多年来,该数据库将被填充,并将包含重要信息。 To make data recoverable I wanted to parse the TableModel into an XML file but this fails because the XML Encoder cannot deal with the JTable / TableModel. 为了使数据可恢复,我想将TableModel解析为一个XML文件,但这失败了,因为XML Encoder无法处理JTable / TableModel。

What are recommendations for saving data from a JTable in "clear text" form efficiently? 关于以有效的“明文”形式从JTable保存数据的建议是什么? Is simply iterating through columns & lines and saving this into a text file (with seperators between column data) line by line a good way? 简单地遍历列和行并将其逐行保存到文本文件中(在列数据之间使用分隔符)是一种好方法吗? My concerns here are that the user might use a separator like ":" (which I might use) as table data and make the parser crash. 我在这里担心的是,用户可能使用诸如“:”之类的分隔符(我可能会使用)作为表数据,并使解析器崩溃。

Thanks for your help. 谢谢你的帮助。

What are recommendations for saving data from a 对从

The API recommends an XMLEncoder API建议使用XMLEncoder

I wanted to parse the TableModel into an XML file but this fails because the XML Encoder cannot deal with the JTable / TableModel. 我想将TableModel解析为XML文件,但是失败了,因为XML编码器无法处理JTable / TableModel。

You need to create a custom encoder. 您需要创建一个自定义编码器。 Below gives two implementations for a DefaultTableModel. 下面给出了DefaultTableModel的两种实现。

//  Following code is a more complete version of:
//  http://stackoverflow.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));
            }
        }
    }
}

You should use and serialize the model only and not the GUI objects (because of the way you're doing it, maybe serialization is not the best option for you). 您应该仅使用模型并对其进行序列化,而不应使用GUI对象(因为这样做的方式,也许序列化不是您的最佳选择)。 If you want to store the table "headers" (layout of the JTable columns) for this purpose is other Model (+/- Table Column Model - I'm without java environment). 如果要为此目的存储表“标题”( JTable列的布局),则使用其他模型(+/-表列模型-我没有Java环境)。

EDIT: If this project is old or important, and you think its worth of investing the time, then maybe you should rethink your Model class? 编辑:如果这个项目是旧的或重要的,并且您认为值得花费时间,那么也许您应该重新考虑您的Model类?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM