从CSV文件提取特征向量时遇NumberFormatException问题求助
解决Java读取CSV时的
NumberFormatException: Illegal embedded sign character异常 嘿,你遇到的这个问题我太熟了!本质就是你在把CSV里的字符串转成数字(int、double这类)的时候,拿到的内容根本不是合法的数字格式——要么是CSV数据本身有坑,要么是你的解析代码没处理好特殊情况。咱一步步来排查解决:
先找问题根源
1. 检查CSV数据本身
先打开你的CSV文件瞅一眼,大概率是这些情况:
- 数字字段里混了多余的正负号,比如
123-45或者+67+89,这种格式转数字肯定炸 - 数字前后藏了空格、全角空格或者看不见的特殊字符(比如制表符)
- 字段里包含了分隔符(比如逗号)但没加引号包裹,导致你的代码把一个字段拆成了多个,比如
"123,45"本来是一个数字,结果被拆成"123和45",转数字自然报错
2. 检查代码的解析逻辑
如果你是用split(",")这种简单粗暴的方式拆分CSV行,那十有八九会踩坑——CSV的规则可比“按逗号拆分”复杂多了,引号包裹的字段、转义字符这些情况,split根本处理不了。另外,如果转数字前没做字符串清理(比如去掉前后空格),或者没处理空字段,也会触发这个异常。
具体修复方案
方案一:先清理字符串再转数字(应急用)
在调用Integer.parseInt()/Double.parseDouble()之前,先把字符串里的垃圾内容清掉,顺便做个格式校验:
// 拿你要转的字段举例 String rawValue = csvFields[你的特征向量索引].trim(); // 先去掉前后空格 // 检查有没有多个正负号(比如"123+45"或者"-67-89") if (rawValue.matches(".*[+-].*[+-].*")) { System.err.println("发现非法数字格式:" + rawValue + ",跳过这条数据"); continue; // 或者抛自定义异常,看你需求 } // 再转数字 try { double featureValue = Double.parseDouble(rawValue); // 把featureValue加入你的特征向量 } catch (NumberFormatException e) { System.err.println("转数字失败:" + rawValue + ",错误信息:" + e.getMessage()); }
方案二:用成熟的CSV解析库(强烈推荐)
自己写CSV解析逻辑简直是给自己挖坑,不如直接用现成的库,比如OpenCSV或者Apache Commons CSV,它们能帮你搞定所有CSV的特殊格式(引号、转义、换行符这些)。
给你整个OpenCSV的示例代码,直接抄就能用:
import com.opencsv.CSVReader; import java.io.FileReader; public class FeatureExtractor { public static void main(String[] args) { String csvPath = "D:\\proj\\你的CSV文件名.csv"; // 用try-with-resources自动关闭流,不用手动写close try (CSVReader reader = new CSVReader(new FileReader(csvPath))) { String[] row; // 逐行读取CSV while ((row = reader.readNext()) != null) { // row里的每个元素都是正确解析后的字段,不用担心拆分错 try { // 假设你的特征向量在第1列(索引0) double feature = Double.parseDouble(row[0].trim()); // 把feature添加到你的特征向量集合里 } catch (NumberFormatException e) { System.err.println("字段[" + row[0] + "]无法转成数字:" + e.getMessage()); } } } catch (Exception e) { e.printStackTrace(); } } }
方案三:检查CSV的编码和换行符
有时候CSV文件的编码有问题(比如UTF-8带BOM),或者换行符是Windows/Linux混着的,也会导致读取到奇怪的字符。可以用记事本打开CSV,选择“另存为”,把编码改成UTF-8(不带BOM),换行符选Windows格式试试。
快速排查小技巧
在代码里加一行日志,把要转数字的字符串用中括号包起来打印,比如:
String value = csvFields[你的索引]; System.out.println("准备转换的字符串:[" + value + "]"); // 中括号能帮你看清有没有前后空格
这样你就能直观看到到底是哪个字符串出问题了,直接去CSV里找对应的行,一下子就能定位原因。
内容的提问来源于stack exchange,提问作者Ma. Andy.
相关产品推荐
相关产品推荐

