【问题标题】:Java ObjectInpuStream reading DefaultTableModel [closed]Java ObjectInpuStream 读取 DefaultTableModel [关闭]
【发布时间】:2020-12-26 19:27:08
【问题描述】:

有一个类保存了另一个类的 DefaultTableModel。

file_path = new File( "c://Database//Directory//" );

file_table_stock_save = new File( file_path , "stockfile.file" );

file_path.mkdirs();

try
{

 file_path..createNewFile();

 fileoutputstream = new FileOutputStream( file_table_stock_save );

 objectoutputstream = new ObjectOutputStream( fileoutputstream );

 objectoutputstream.writeObject( stock.defaulttablemodel );

 objectoutputstream.close();

 fileoutputstream.close();

}

  catch( Exception exception )
  {.....}

现在是读取 DefaultTableModel 的方式

file = new File( "C://Database//Directory//" , "stockfile.file" );
        
object = new Object();
        
if( file.exists() )
{
        
 try
 {
        
  fileinputstream = new FileInputStream( file );
  objectinputstream = new ObjectInputStream( fileinputstream );
        
  object = objectinputstream.readObject();
        
  objectinputstream.close();
  fileinputstream.close();
        
 }
        
 catch( Exception exception )
 {}
        
 try
 {
        
  if( !( object == null ) )
  defaulttablemodel = ( DefaultTableModel ) object;
        
 }
        
 catch( Exception exception )
 {......}

问题是文件始终存在,但有时无法读取文件。如何找出问题所在?类应该实现可序列化吗? JTable 中的空单元格在读取时会导致错误吗?

【问题讨论】:

  • 请注意:catch( Exception exception ) {} 是非常糟糕的做法
  • “无法读取”是什么意思?

标签: java swing object fileinputstream fileoutputstream


【解决方案1】:

首先,我永远不会序列化 DefaultTableModel,否则你会序列化你不想序列化的东西,包括侦听器等等。最好保持简单,并序列化数据,并且只序列化数据。我将序列化包含感兴趣数据的数据向量。用它来用检索到的数据重建一个新的表模型。

幸运的是 DefaultTableModel 有一个方法 .getDataVector() 从模型中检索 Vector<Vector> 来保存模型中的所有数据。如果您必须使用序列化,我会使用它来保存和检索数据。

在下面的代码中,我有一个扩展 DefaultTableModel 的简单类,它允许使用数据向量重新创建模型,使用常量向量来保存表格标题:

class MyModel extends DefaultTableModel {
    public static final String[] HEADERS = { "One", "Two", "Three" };
    public static final Vector<String> V_HEADERS = new Vector<>(Arrays.asList(HEADERS));

    public MyModel(Vector<Vector<Object>> data) {
        super(data, V_HEADERS);
    }

    public MyModel() {
        super(HEADERS, 0);
    }

}

然后我可以通过此代码对模型持有的数据进行序列化和反序列化以进行序列化:

// assuming that the model is held in a variable called "myModel"
Vector tableData = myModel.getDataVector();
        // file name is held by DATA_FILE String constant
try (FileOutputStream fos = new FileOutputStream(DATA_FILE); 
        ObjectOutputStream oos = new ObjectOutputStream(fos);) {
    oos.writeObject(tableData);  // writes my data 

} catch (IOException ioe) {
    ioe.printStackTrace(); // always catch and handle exceptions
}

我可以将数据读回模型,然后通过以下方式读入 JTable:

// again DATA_FILE is our file's name
try (FileInputStream fis = new FileInputStream(DATA_FILE); 
        ObjectInputStream ois = new ObjectInputStream(fis)) {
    // read the data vector in with the ObjectInputStream
    Vector<Vector<Object>> tableData = (Vector<Vector<Object>>) ois.readObject();
    
    // create a new table model with the data
    myModel = new MyModel(tableData);
    
    // set the JTable with the new model
    table.setModel(myModel);
} catch (IOException | ClassNotFoundException e) {
    e.printStackTrace();
}

一个工作示例:

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Vector;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public class Gui01 extends JPanel {
    public static final String DATA_FILE = "tableData.dat";
    private MyModel myModel = new MyModel();
    private JTable table = new JTable(myModel);

    public Gui01() {
        int maxRow = 5;
        for (int row = 0; row < maxRow; row++) {
            Vector<Object> rowData = new Vector<>();
            for (int col = 0; col < table.getColumnCount(); col++) {
                Integer cell = row * table.getColumnCount() + col;
                rowData.add(cell);
            }
            myModel.addRow(rowData);
        }

        saveTable();

        JButton saveTableBtn = new JButton("Save Table");
        saveTableBtn.setMnemonic(KeyEvent.VK_S);
        saveTableBtn.addActionListener(e -> saveTable());

        JButton clearTableBtn = new JButton("Clear Table");
        clearTableBtn.setMnemonic(KeyEvent.VK_C);
        clearTableBtn.addActionListener(e -> clearTable());

        JButton retrieveTableBtn = new JButton("Retrieve Table");
        retrieveTableBtn.setMnemonic(KeyEvent.VK_R);
        retrieveTableBtn.addActionListener(e -> retrieveTable());

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(saveTableBtn);
        buttonPanel.add(clearTableBtn);
        buttonPanel.add(retrieveTableBtn);

        setLayout(new BorderLayout());
        add(new JScrollPane(table));
        add(buttonPanel, BorderLayout.PAGE_END);

    }

    @SuppressWarnings("rawtypes")
    private void saveTable() {
        Vector tableData = myModel.getDataVector();
        try (FileOutputStream fos = new FileOutputStream(DATA_FILE);
                ObjectOutputStream oos = new ObjectOutputStream(fos);) {
            oos.writeObject(tableData);

        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    private void clearTable() {
        myModel.setRowCount(0);
    }

    @SuppressWarnings("unchecked")
    private void retrieveTable() {
        try (FileInputStream fis = new FileInputStream(DATA_FILE); 
                ObjectInputStream ois = new ObjectInputStream(fis)) {
            Vector<Vector<Object>> tableData = (Vector<Vector<Object>>) ois.readObject();
            myModel = new MyModel(tableData);
            table.setModel(myModel);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        Gui01 mainPanel = new Gui01();
        JFrame frame = new JFrame("Gui01");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}
class MyModel extends DefaultTableModel {
    public static final String[] HEADERS = { "One", "Two", "Three" };
    public static final Vector<String> V_HEADERS = new Vector<>(Arrays.asList(HEADERS));

    public MyModel(Vector<Vector<Object>> data) {
        super(data, V_HEADERS);
    }

    public MyModel() {
        super(HEADERS, 0);
    }
}

【讨论】:

  • 当我尝试编译您的“MyModel”类时,我收到错误消息:没有为 DefaultTableModel(Vector,Vector) 找到合适的构造函数 super(data, V_HEADERS) ;. DefaultTableModel 的参数应该是 Vector&lt;Vector&lt;Object&gt;&gt; 而不是 Vector&lt;Object&gt; 我相信。
  • @camickr:谢谢你检查这个。出于某种原因,它在我的 PC 上运行(可能使用早期版本的 Java)。我已经更新了代码,所以希望它适用于每个 Java 版本。再次,我真诚地感谢你。
  • (1+) 现在对我有用。
猜你喜欢
  • 1970-01-01
  • 2017-09-18
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-04
  • 2012-01-23
相关资源
最近更新 更多