You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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++;
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:55:28