JTable展示CSV数据异常求助:数据未正常显示且报数组越界
问题排查与解决方案
我来帮你解决这两个核心问题:ArrayIndexOutOfBoundsException异常,以及CSV数据无法正确显示在JTable中的问题。
1. 数组越界异常(java.lang.ArrayIndexOutOfBoundsException: 16)
问题原因
你的MiModel表格模型固定了18列(对应columnNames数组的长度),但CSV文件中存在某一行拆分后的数组长度不足18。比如某一行只有16个元素,当表格尝试访问第17个索引(索引从0开始,对应第18列)时,就会触发数组越界异常。
解决方案
我们可以通过两个步骤来解决:一是在添加CSV数据时,确保每一行的元素数量与表格列数一致;二是在getValueAt方法中添加边界检查,双重保险避免越界。
修改MiModel类的代码:
class MiModel extends AbstractTableModel { private String [] columnNames = {"1","2","3","4","5","6","7","8","9","10", "11","12","13","14","15","16","17","18"}; private ArrayList<String[]>Data = new ArrayList<>(); public void AddCSVData(ArrayList<String[]> DataIn){ ArrayList<String[]> processedData = new ArrayList<>(); int targetColCount = columnNames.length; // 处理每一行,补全不足的列 for(String[] row : DataIn){ String[] processedRow = new String[targetColCount]; // 复制已有数据 System.arraycopy(row, 0, processedRow, 0, Math.min(row.length, targetColCount)); // 不足的列填充空字符串 for(int i = row.length; i < targetColCount; i++){ processedRow[i] = ""; } processedData.add(processedRow); } this.Data = processedData; this.fireTableDataChanged(); } @Override public int getColumnCount(){ return columnNames.length; } @Override public int getRowCount(){ return Data.size(); } @Override public String getColumnName(int col){ return columnNames[col]; } @Override public Object getValueAt(int row, int col){ // 边界检查,避免越界 if(row >= Data.size() || col >= Data.get(row).length){ return ""; } return Data.get(row)[col]; } }
2. CSV数据未正确显示(丢失行数据)
问题原因
在CSVFile的ReadCSVFile方法中,你每次循环调用了两次brd.readLine():第一次在while(brd.readLine()!= null)的条件判断中读取了一行,但没有保存;第二次在循环体内又读取下一行,导致一半的行数据被跳过,自然无法在表格中显示完整。
解决方案
修改ReadCSVFile方法,只调用一次readLine()并保存结果,同时注意关闭流避免资源泄漏:
public class CSVFile { public ArrayList<String[]> ReadCSVFile(File DataFile){ ArrayList<String[]> Rs = new ArrayList<>(); // 移到方法内,避免多次调用时数据残留 try{ BufferedReader brd = new BufferedReader (new FileReader(DataFile)); String st; // 一次读取一行,直到返回null while((st = brd.readLine())!= null){ // 注意:如果CSV字段包含逗号(如带引号的字段),split(",")会出错,建议用专业CSV库 String[] oneRow = st.split(","); Rs.add(oneRow); System.out.println(Arrays.toString(oneRow)); } brd.close(); // 关闭流 }catch(Exception ex){ String errmsg = ex.getMessage(); System.out.println("File not Found: "+errmsg); } return Rs; } }
额外优化建议
- 避免空指针异常:在
actionPerformed方法中,要先判断用户是否确认选择了文件,否则getSelectedFile()会返回null:
public void actionPerformed(ActionEvent Event) { JFileChooser file_chooser = new JFileChooser(); int returnVal = file_chooser.showOpenDialog(null); // 检查用户是否确认选择文件 if(returnVal == JFileChooser.APPROVE_OPTION){ CSVFile Rd = new CSVFile(); MiModel NewModel = new MiModel(); this.Table.setModel(NewModel); File DataFile = file_chooser.getSelectedFile(); ArrayList<String[]> rs2 = Rd.ReadCSVFile(DataFile); NewModel.AddCSVData(rs2); System.out.println("Rows: " +NewModel.getRowCount()); System.out.println("Cols: " +NewModel.getColumnCount()); } }
- 专业CSV解析:手动用
split(",")无法处理带引号的字段(比如字段内容包含逗号的情况),建议使用成熟的CSV库如OpenCSV,它能正确处理各种CSV格式的细节。
内容的提问来源于stack exchange,提问作者Fortune Dludla
相关产品推荐
相关产品推荐

