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

由于保存之前/之后的CSV差异(Java w/Apache Commons CSV)导致分析错误,java,csv,encoding,apache-commons-csv,Java,Csv,Encoding,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); //init

我有一个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会在末尾添加所需的逗号,这样我的程序就不会抱怨没有足够的头来读取

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

前(失败):“数据”、“数据”、“数据”、“数据”

之后(工作):“数据”,“数据”,“数据”,“数据”,“数据”,“数据”,“数据”,“数据”,“数据”

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

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

提前谢谢

编辑#1:

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

^M
在Excel中打开并保存后,我的37个空字段如下所示:

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,^M
这是Windows编码差异吗?

请尝试以下方法: 为给定文件创建解析器。 解析(文件文件、字符集、字符集、CSVFormat格式)

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


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

或者可以尝试使用AllowMissingColumnNames

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

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

也许您可以通过创建自己的子类来处理它,该子类位于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()
方法都能正常工作。如果文件可以很容易地放入内存,只需读取文件并将固定版本写入新版本,然后在CSVParser中创建一个。这与添加缺少的列有什么关系?可能与AllowMissingColumnNames有关?CSVFormat csvFileFormat=CSVFormat.DEFAULT.withHeader(文件头映射).withAllowMissingColumnNames();不要试图猜测。如果你研究过这件事并知道答案,那就回答吧。但仅仅抛出未经测试的建议并不是处理堆栈溢出的方式。另外,你应该格式化你的答案,特别是那些代码部分。不,这会推断出列在那里,没有名字。我的专栏只是不在那里(在我保存文件之前)很好的输入,谢谢你的时间。我还刚刚读到RFC 4180是Excel将“不合规”CSV文件保存到的标准,这也是我保存后看到逗号的原因。我将寻求实现我自己的阅读器,因为我必须以编程方式解决它。
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; }
        }
    }