Java项目:实现JTable与Excel/CSV的读写及修改保存
Java JTable数据修改后保存回Excel/CSV文件的实现方案
问题描述
我正在开发一个Java项目,需求是读取数据库导出的动态Excel/CSV文件,将数据展示到JTable中,支持修改JTable的数据后保存回原文件。目前已经实现了文件的动态读取和展示,但不知道如何将修改后的内容保存回原文件,上司提到了「文件绑定」的思路,但没找到相关方案,求方向指导。
现有代码拆分到不同类中提升可读性:hope类为主入口,index类创建触发文件选择器的按钮,FileChooser类负责文件选择,GUI类为核心(根据文件扩展名调用不同读取方法并将数据放入JTable),Excel/CSV类负责解析对应文件,Matrix类将数据字符串转换为字符串矩阵。
核心思路:基于TableModel实现数据绑定
上司说的「文件绑定」本质是让JTable的数据模型(TableModel)和文件读写逻辑关联,JTable的所有修改都实时存在TableModel中,保存时直接从Model提取数据写入文件。你当前用二维数组创建JTable的方式无法追踪数据变化,必须改用DefaultTableModel作为数据载体。
具体实现步骤
- 替换JTable的数据模型:放弃用二维数组直接创建JTable,改用
DefaultTableModel承载表头和数据,后续所有修改都基于Model操作。 - 添加保存触发逻辑:在表格窗口中新增保存按钮,点击时根据文件类型调用对应写入方法。
- 实现文件写入方法:给Excel、CSV类新增写入逻辑,将TableModel中的数据转换为对应格式写入原文件。
- 优化读取逻辑:去掉字符串拼接再拆分的中转步骤(避免数据含空格时出错),直接读取数据到二维数组后加载到Model。
代码修改示例
1. 修改GUI类,添加保存按钮并使用DefaultTableModel
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class GUI { static void creation(final String filename, final String estensione){ String[][] datMat = null; String[] colonne = null; // 直接读取表头和数据矩阵,跳过字符串中转 if(estensione.equals(".xlsx")){ colonne = Excel.getHeaders(filename); datMat = Excel.getDataMatrix(filename); } else if(estensione.equals(".csv")){ colonne = CSV.getHeaders(filename); datMat = CSV.getDataMatrix(filename); } JFrame frame = new JFrame("数据编辑"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); // 使用DefaultTableModel作为数据载体 DefaultTableModel model = new DefaultTableModel(datMat, colonne); JTable table = new JTable(model); frame.add(new JScrollPane(table), BorderLayout.CENTER); // 添加保存按钮 JButton saveBtn = new JButton("保存到文件"); frame.add(saveBtn, BorderLayout.SOUTH); saveBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 根据文件类型调用写入方法 if(estensione.equals(".xlsx")){ Excel.writeToFile(filename, model); } else if(estensione.equals(".csv")){ CSV.writeToFile(filename, model); } JOptionPane.showMessageDialog(frame, "保存成功!"); } }); frame.setSize(600, 600); frame.setLocationRelativeTo(null); frame.setVisible(true); } }
2. 修改Excel类,添加表头、数据读取和写入方法
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.File; import java.util.Iterator; public class Excel { // 获取表头 static String[] getHeaders(String filename){ String[] headers = null; try{ FileInputStream fis = new FileInputStream(new File(filename)); XSSFWorkbook wb = new XSSFWorkbook(fis); Sheet sheet = wb.getSheetAt(0); Row headerRow = sheet.getRow(0); int colCount = headerRow.getPhysicalNumberOfCells(); headers = new String[colCount]; for(int i=0; i<colCount; i++){ headers[i] = headerRow.getCell(i).getStringCellValue(); } fis.close(); }catch(Exception e){e.printStackTrace();} return headers; } // 获取数据矩阵 static String[][] getDataMatrix(String filename){ String[][] data = null; try{ FileInputStream fis = new FileInputStream(new File(filename)); XSSFWorkbook wb = new XSSFWorkbook(fis); Sheet sheet = wb.getSheetAt(0); int rowCount = sheet.getPhysicalNumberOfRows(); int colCount = sheet.getRow(0).getPhysicalNumberOfCells(); data = new String[rowCount-1][colCount]; // 跳过表头 Iterator<Row> rowIterator = sheet.iterator(); rowIterator.next(); // 跳过表头行 int rowIdx = 0; while(rowIterator.hasNext()){ Row row = rowIterator.next(); Iterator<Cell> cellIterator = row.cellIterator(); int colIdx = 0; while(cellIterator.hasNext()){ Cell cell = cellIterator.next(); switch(cell.getCellType()){ case STRING: data[rowIdx][colIdx] = cell.getStringCellValue(); break; case NUMERIC: data[rowIdx][colIdx] = String.valueOf((int)cell.getNumericCellValue()); break; default: data[rowIdx][colIdx] = ""; } colIdx++; } rowIdx++; } fis.close(); }catch(Exception e){e.printStackTrace();} return data; } // 写入Excel文件 static void writeToFile(String filename, DefaultTableModel model){ try{ XSSFWorkbook wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("数据"); // 写入表头 Row headerRow = sheet.createRow(0); for(int i=0; i<model.getColumnCount(); i++){ Cell cell = headerRow.createCell(i); cell.setCellValue(model.getColumnName(i)); } // 写入数据行 for(int i=0; i<model.getRowCount(); i++){ Row row = sheet.createRow(i+1); for(int j=0; j<model.getColumnCount(); j++){ Cell cell = row.createCell(j); Object value = model.getValueAt(i, j); cell.setCellValue(value != null ? value.toString() : ""); } } FileOutputStream fos = new FileOutputStream(new File(filename)); wb.write(fos); fos.close(); wb.close(); }catch(Exception e){e.printStackTrace();} } // 保留原有的carica、riga、colonna方法(如需兼容旧逻辑) }
3. 修改CSV类,添加表头、数据读取和写入方法
import java.io.*; import java.util.ArrayList; import java.util.List; public class CSV { // 获取表头 static String[] getHeaders(String filename){ String[] headers = null; try{ BufferedReader reader = new BufferedReader(new FileReader(filename)); String line = reader.readLine(); if(line != null){ headers = line.split(","); } reader.close(); }catch(Exception e){e.printStackTrace();} return headers; } // 获取数据矩阵 static String[][] getDataMatrix(String filename){ List<String[]> dataList = new ArrayList<>(); try{ BufferedReader reader = new BufferedReader(new FileReader(filename)); reader.readLine(); // 跳过表头 String line; while((line = reader.readLine()) != null){ dataList.add(line.split(",")); } reader.close(); }catch(Exception e){e.printStackTrace();} // 转换为二维数组 String[][] data = new String[dataList.size()][]; for(int i=0; i<dataList.size(); i++){ data[i] = dataList.get(i); } return data; } // 写入CSV文件 static void writeToFile(String filename, DefaultTableModel model){ try{ BufferedWriter writer = new BufferedWriter(new FileWriter(filename)); // 写入表头 StringBuilder headerSb = new StringBuilder(); for(int i=0; i<model.getColumnCount(); i++){ headerSb.append(model.getColumnName(i)); if(i != model.getColumnCount()-1){ headerSb.append(","); } } writer.write(headerSb.toString()); writer.newLine(); // 写入数据行 for(int i=0; i<model.getRowCount(); i++){ StringBuilder rowSb = new StringBuilder(); for(int j=0; j<model.getColumnCount(); j++){ Object value = model.getValueAt(i, j); rowSb.append(value != null ? value.toString() : ""); if(j != model.getColumnCount()-1){ rowSb.append(","); } } writer.write(rowSb.toString()); writer.newLine(); } writer.close(); }catch(Exception e){e.printStackTrace();} } // 保留原有的carica、riga、colonna方法(如需兼容旧逻辑) }
额外优化建议
- 移除Matrix类:当前字符串拼接拆分的逻辑容易因数据含空格出错,直接使用上述修改后的读取方法即可。
- 优化异常处理:用弹窗提示用户错误,而非仅打印控制台。
- 添加数据校验:保存前检查必填字段是否为空,避免无效数据写入文件。
原始代码
HOPE CLASS
public class hope { public static void main(String[] args) { index.index(); } }
INDEX CLASS
import java.awt.event.*; import javax.swing.*; public class index { static void index(){ JFrame frame = new JFrame("FILE"); JButton button=new JButton("SCEGLI FILE"); frame.setSize(500,500); frame.add(button); frame.setLayout(null); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); button.setBounds(150,150,200,200); frame.setVisible(true); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String filename = FileChooser.filename(); String estensione = filename.substring(filename.lastIndexOf("."), filename.length()); GUI.creation(filename, estensione); } }); } }
FILE CHOOSER CLASS
import java.io.File; import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileNameExtensionFilter; public class FileChooser { static String filename(){ JFileChooser chooser=new JFileChooser(); FileFilter xlsx = new FileNameExtensionFilter("Excel File", "xlsx"); FileFilter csv = new FileNameExtensionFilter("CSV File", "csv"); FileFilter xml = new FileNameExtensionFilter("XML File", "xml"); FileFilter json = new FileNameExtensionFilter("JSON file", "json"); chooser.setFileFilter(xlsx); chooser.setFileFilter(csv); chooser.setFileFilter(xml); chooser.setFileFilter(json); chooser.setAcceptAllFileFilterUsed(false); chooser.showOpenDialog(null); File file = chooser.getSelectedFile(); String filename = file.getAbsolutePath(); return filename; } }
EXCEL READER CLASS
import java.io.File; import java.io.FileInputStream; import java.util.Iterator; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class Excel { //file parse static String carica(String filename){ String data = ""; try{ File file = new File(filename); FileInputStream fis = new FileInputStream(file); XSSFWorkbook wb = new XSSFWorkbook(fis); XSSFSheet sheet = wb.getSheetAt(0); Iterator<Row> itr = sheet.iterator(); while (itr.hasNext()){ Row row = itr.next(); Iterator<Cell> cellIterator = row.cellIterator(); while (cellIterator.hasNext()){ Cell cell = cellIterator.next(); switch (cell.getCellType()){ case Cell.CELL_TYPE_STRING: data += cell.getStringCellValue() + " "; break; case Cell.CELL_TYPE_NUMERIC: int y; y= (int) cell.getNumericCellValue(); data += y + " "; break; default: } } } fis.close(); }catch(Exception e){System.out.println("Errore" + e);} return data; } //row number static int riga(String filename){ int r=0; try{ File file = new File(filename); FileInputStream fis = new FileInputStream(file); XSSFWorkbook wb = new XSSFWorkbook(fis); XSSFSheet sheet = wb.getSheetAt(0); r = sheet.getPhysicalNumberOfRows(); }catch(Exception e){} return r; } //column number static int colonna(String filename){ int c = 0; try{ File file = new File(filename); FileInputStream fis = new FileInputStream(file); XSSFWorkbook wb = new XSSFWorkbook(fis); XSSFSheet sheet = wb.getSheetAt(0); c = sheet.getRow(0).getPhysicalNumberOfCells(); }catch(Exception e){System.out.println("Errore" + e);} return c; } }
CSV READER CLASS
import java.io.BufferedReader; import java.io.FileReader; import java.util.Scanner; public class CSV { //file parse static String carica(String filename){ String data = ""; try { Scanner scanIn = new Scanner(new BufferedReader(new FileReader(filename))); scanIn.useDelimiter(","); String [] InArray; String s; while(scanIn.hasNextLine()){ s = scanIn.nextLine(); InArray = s.split(","); for(int i=0;i<InArray.length;i++){ data += InArray[i] + " "; } } } catch (Exception e) { e.printStackTrace(); } return data; } //row number static int riga(String filename){ int r=0; try { Scanner scanIn = new Scanner(new BufferedReader(new FileReader(filename))); scanIn.useDelimiter(","); String [] InArray; String s; while(scanIn.hasNextLine()){ s = scanIn.nextLine(); InArray = s.split(","); r++; } }catch(Exception e){System.out.println("Errore" + e);} return r; } //column number static int colonna(String filename){ int c = 0; try { Scanner scanIn = new Scanner(new BufferedReader(new FileReader(filename))); scanIn.useDelimiter(""); String [] InArray; String s; while(scanIn.hasNextLine()){ s = scanIn.nextLine(); InArray = s.split(","); c = InArray.length; } }catch(Exception e){System.out.println("Errore" + e);} return c; } }
MATRIX CLASS
public class Matrix { //matrix data static String[][] mat(String data, int r, int c){ String[] datArray = null; datArray = data.split(" "); final String[][] datMat = new String[r-1][c]; int x = c; for (int i = 1; i< r; i++){ for (int j = 0; j< c; j++){ datMat[i-1][j] = datArray[x]; x++; } } return datMat; } //column names static String[] colonne(String data, int r, int c){ String[] datArray = null; datArray = data.split(" "); final String colonna[] = new String[c]; int x = 0; for (int i = 0; i< c; i++){ colonna[i] = datArray[x]; x++;
相关产品推荐
相关产品推荐

