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

CSV解析异常:含引号包裹逗号字段时抛出ArrayIndexOutOfBoundsException

解决CSV含逗号字段解析时的ArrayIndexOutOfBoundsException问题

嘿,这个坑我之前手动写CSV解析器的时候踩过好几次!问题出在你大概率是直接用了String.split(",")来分割每行,这种简单处理完全没法识别引号包裹的字段里的逗号——它会把引号里的逗号也当成分隔符,导致分割出来的数组元素数量和你预期的不一致,最后调用r.get(1)的时候自然就越界了。

最省心的解决方案:用成熟的CSV解析库

别自己造轮子了,手动处理CSV的各种边缘情况(比如引号里的引号、字段内换行、转义字符等)太容易出错。推荐用OpenCSV,这是Java/Android生态里最常用的CSV处理库之一,专门处理这些场景。

举个在AsyncTask里使用的例子:

import com.opencsv.CSVReader;
import java.io.FileReader;
import java.io.IOException;

// 你的AsyncTask子类
private class CsvParseTask extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... voids) {
        CSVReader reader = null;
        try {
            // 替换成你的CSV文件路径
            reader = new CSVReader(new FileReader("/path/to/your/file.csv"));
            String[] row;
            // 逐行读取,自动处理引号包裹的含逗号字段
            while ((row = reader.readNext()) != null) {
                // 这里的row已经是正确分割后的字段数组
                if (row.length >= 2) { // 先做长度检查,避免意外
                    String targetField = row[1];
                    // 处理你的业务逻辑
                } else {
                    // 处理格式异常的行,比如字段数量不足
                    Log.w("CSVParse", "Invalid row with insufficient fields");
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            // 处理IO异常
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

如果非要自己写解析逻辑

如果你不想引入第三方库,那得手动实现一个能识别引号状态的解析方法,核心思路是遍历每行的字符,判断当前是否处于引号包裹状态——只有不在引号里的逗号才会被当成分隔符:

private List<String> parseCsvLine(String line) {
    List<String> fields = new ArrayList<>();
    StringBuilder currentField = new StringBuilder();
    boolean insideQuotes = false;

    for (char c : line.toCharArray()) {
        if (c == '"') {
            // 切换引号状态
            insideQuotes = !insideQuotes;
        } else if (c == ',' && !insideQuotes) {
            // 不在引号内的逗号才是分隔符,添加当前字段并重置
            fields.add(currentField.toString().trim());
            currentField.setLength(0);
        } else {
            // 普通字符,添加到当前字段
            currentField.append(c);
        }
    }
    // 添加最后一个字段
    fields.add(currentField.toString().trim());
    return fields;
}

然后在你的AsyncTask里替换掉split的逻辑:

// 假设line是读取到的CSV行
List<String> rowFields = parseCsvLine(line);
if (rowFields.size() >= 2) {
    String field = rowFields.get(1);
    // 处理逻辑
} else {
    // 处理异常行
}

额外提醒

  • 手动解析的方法还没处理转义引号(CSV规范里用两个连续引号""表示字段内的一个引号),如果你的CSV有这种场景,得在遍历字符的时候加判断。
  • 不管用哪种方式,都要先检查数组/集合的长度再调用get(),避免因为某行CSV格式本身错误导致的越界。
  • Android平台上要注意文件读取的动态权限(Android 6.0+),不然会出现IO异常。

内容的提问来源于stack exchange,提问作者Jo Momma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:21:42