保存前/保存后由于CSV差异导致分析错误(Java w/Apache Commons CSV)



我有一个37列的CSV文件,我正在用Apache Commons CSV 1.2用Java进行解析。我的设置代码如下:

//initialize FileReader object
FileReader fileReader = new FileReader(file);
//intialize CSVFormat object
CSVFormat csvFileFormat = CSVFormat.DEFAULT.withHeader(FILE_HEADER_MAPPING);
//initialize CSVParser object
CSVParser csvFileParser = new CSVParser(fileReader, csvFileFormat);
//Get a list of CSV file records
List<CSVRecord> csvRecords = csvFileParser.getRecords();
// process accordingly

我的问题是,当我将要处理的CSV复制到目标目录并运行解析程序时,我会得到以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: Index for header 'Title' is 7 but CSVRecord only has 6 values!
        at org.apache.commons.csv.CSVRecord.get(CSVRecord.java:110)
        at launcher.QualysImport.createQualysRecords(Unknown Source)
        at launcher.QualysImport.importQualysRecords(Unknown Source)
        at launcher.Main.main(Unknown Source)

但是,如果我将文件复制到目标目录,打开并保存它,然后重试该程序,它就会工作。打开并保存CSV会在末尾添加所需的逗号,这样我的程序就不会因为没有足够的标题而感到沮丧。

对于上下文,这里是保存之前/之后的示例行:

之前(失败):"数据","数据"、"数据"one_answers"数据"

在(工作)之后:"data","data"

所以我的问题是:为什么当我打开并保存CSV格式时会发生更改?我没有更改任何值或编码,保存时MS-DOS或常规.csv格式的行为相同。此外,我在测试中使用Excel进行复制/打开/保存。

我需要使用一些编码或格式设置吗?我可以用程序解决这个问题吗?

提前感谢!

编辑#1:

对于其他上下文,当我第一次查看原始文件中的空行时,它只有新行^M字符,如下所示:

^M

在Excel中打开并保存后,我的所有37个空字段都是这样的:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,^M

这是Windows编码的差异吗?

也许这是与最初生成文件的内容的兼容性问题。Excel似乎接受一个空行作为有效行,每列中都有空字符串,列数与其他行匹配。然后,它根据带有列分隔符的CSV约定进行保存。(^M是回车字符;在Microsoft系统中,它位于文本文件中一行末尾的换行字符之前)

也许您可以通过创建自己的Reader子类来处理它,该子类位于FileReader和CSVParser之间。您的阅读器将读取一行,如果该行为空,则返回一行,其中包含正确的逗号数。否则,只需按原样返回行。

例如:

class MyCSVCompatibilityReader extends BufferedReader
    {
    private final BufferedReader delegate;
    public MyCSVCompatibilityReader(final FileReader fileReader)
        {
        this.delegate = new BufferedReader(fileReader);
        }
    @Override
    public String readLine()
        {
        final String line = this.delegate.readLine();
        if ("".equals(line.trim())
            { return ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"; }
        else
            { return line; }
        }
    }

在实现接口时,还有许多其他细节需要正确实现。您需要将调用传递给所有其他方法(close、ready、reset、skip等),并确保各种read()方法都能正确工作。如果文件可以很容易地放入内存,那么只需读取文件并将固定版本写入新的StringWriter,然后在CSVParser中创建StringReader可能会更容易。

也许可以试试这个:为给定的文件创建一个解析器。parse(文件文件,字符集字符集,CSVFormat格式)

//导入导入java.nio.charset.StandardCharsets;//标准字符集.UTF_8

注意:此方法使用FileReader.FileReader(java.io.File)在内部创建一个FileReader,而FileReader又依赖于执行代码的JVM的默认编码。

或者尝试使用AllowMissingColumnNames?

//intialize CSVFormat object 
CSVFormat csvFileFormat = CSVFormat.DEFAULT.withHeader(FILE_HEADER_MAPPING).withAllowMissingColumnNames();

相关内容

  • 没有找到相关文章

最新更新