2015-09-07 1 views
0

dans mon projet actuel je travaille avec un JTable et DefaultTableModel. Tout fonctionne jusqu'ici et actuellement pour sauver le TableModel je sérialise simplement l'objet sur le disque.Bon moyen de stocker des données JTable pour long terme?

Comme cela peut être un moyen raisonnable d'enregistrer et de charger les données, je n'aime pas le fait que les données soient complètement "obfusquées"/sous forme d'octets. Cela rend les données presque impossibles à sauver si quelque chose de mal arrive. Un autre problème est l'UUID de numérotation qui rend plus difficile la mise à jour de mon programme et ne rend pas les données non chargeables.

La base de données sera alimentée au fil du temps et contiendra des informations importantes. Pour rendre les données récupérables j'ai voulu analyser le TableModel dans un fichier XML mais cela échoue parce que le codeur XML ne peut pas traiter le JTable/TableModel.

Quelles sont les recommandations pour l'enregistrement efficace des données d'un JTable en "texte clair"? Est-ce simplement itératif à travers les colonnes & lignes et enregistrez cela dans un fichier texte (avec séparateurs entre les données de la colonne) ligne par ligne un bon moyen? Mes préoccupations ici sont que l'utilisateur peut utiliser un séparateur comme ":" (que je pourrais utiliser) comme données de table et faire planter l'analyseur.

Merci pour votre aide.

+4

Base de données serait ma première recommandation, peut XML ou JSON venir en second lieu. Vous pouvez regarder quelque chose comme [Introduction à JAXB] (https://docs.oracle.com/javase/tutorial/jaxb/intro/), qui vous permettra de définir une série d'annotations dans votre objet de données (POJO) qui permettra à l'API de l'encoder/de le décoder – MadProgrammer

+0

Une base de données permet également plus de flexibilité, comme les requêtes SQL, les modifications de la base de données, les vidages textuels pour d'autres DB/Excel et ainsi de suite. Vous pouvez utiliser une base de données intégrée comme Derby ou H2. J'aime la mention de JAXB avec les annotations par MadProgrammer, pour avoir des classes d'objets pour les lignes. –

Répondre

0

Vous devez utiliser et sérialiser uniquement le modèle et non les objets de l'interface graphique (à cause de la façon dont vous le faites, peut-être que la sérialisation n'est pas la meilleure option pour vous). Si vous voulez stocker la table "en-têtes" (disposition des colonnes JTable) à cet effet est un autre modèle (+/- Table Column Model - Je suis sans environnement Java).

EDIT: Si ce projet est ancien ou important, et que vous pensez qu'il vaut la peine d'investir du temps, alors peut-être devriez-vous repenser votre classe Model?

+0

La sérialisation d'objets n'est pas destinée au stockage à long terme d'objets et, comme le PO l'a souligné, elle comporte de nombreuses limitations. Il ya beaucoup de meilleures options disponibles maintenant, JAXB a été l'un d'entre eux – MadProgrammer

+0

Merci pour votre réponse. Bien sûr, je sérialise le modèle, pas l'élément GUI. La sérialisation de la JTable n'aurait aucun effet car elle stocke les données ** non **. – Flatron

2

Quelles sont les recommandations pour l'enregistrement des données à partir d'un

L'API recommande une XMLEncoder

Je voulais analyser le TableModel dans un fichier XML, mais cela échoue parce que le codeur XML ne peut pas traiter avec le JTable/TableModel.

Vous devez créer un encodeur personnalisé. Ci-dessous donne deux implémentations pour un 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)); 
      } 
     } 
    } 
} 
+0

intéressant .... – mKorbel