OPENCSV 将第一列填充为空

问题描述 投票:0回答:5

我正在尝试使用 HeaderColumnNameMappingStrategy 使用 opencsv 读取 csv 文件。 Opencsv 每次都会将我的 csv 第一列填充为 null。 这是我的代码:

实体类:

@Entity
@Table(name = "MyEntity")
public class MyEntity {

    @CsvBindByName(column = "status", required = true)
    @Column(name = "status", length = 5, nullable = false)
    private String status;

    @CsvBindByName(column = "type", required = true)
    @Column(name = "type", length = 5, nullable = false)
    private String type;

    @CsvBindByName(column = "percentage", required = true)
    @Column(name = "percentage", nullable = false)
    private Integer percentage;

    @Column(name = "date", nullable = false)
    @CsvBindByName(column = "date", required = true)
    @CsvDate(value = "yyyy-MM-dd")
    private Date date;
}

阅读逻辑:

 final HeaderColumnNameMappingStrategy<MyEntity> mpngInfo= new HeaderColumnNameMappingStrategy<>();
                mappingInfo.setType(MyEntity.class);
 final CsvToBean<MyEntity> csvToBean = new CsvToBean<>();
File file = new File(<path>);
CSVReader reader = new CSVReader(new FileReader(file),';');
 final List<MyEntity> list = csvToBean.parse(mpngInfo, reader, true);
//here in list the first column is always populated as null.

我的 CSV :

类型;状态;百分比;日期 活跃;美元;25;2014-01-01 活跃;英镑;25;2014-01-01

注意:即使我将“类型”与“百分比”切换,它也会开始将百分比填充为空,因为“百分比”列成为第一列。

我找出了文件第一个字符的问题。 就我而言,它是“”类型;状态;百分比;日期

问题列在这里: 从文本文件中读取的第一个字符:

如何在 opencsv 中解决这个问题?有什么建议吗?

opencsv
5个回答
30
投票

我遇到了同样的问题。

解决方案

我再次通过utf-8无BOM保存了csv文件。
然后第一列设置为正确的值。
无需更改任何代码。
我使用名为 sakura 的文本编辑器。选择编码为 utf-8 后,启用了 BOM 复选框。取消选中它并保存 csv 文件。我认为其他编辑器具有相同的 BOM 选项。

原因

BOM 编码的 UTF-8 字符串将从以下三个字节开始。 EFBB BF

添加到 csv 文件的三个字节可能会更改您的第一个列名称。


4
投票

在 intellij 中,您只需单击文件,然后单击顶部菜单“文件”->“文件属性”->“删除 BOM”。这将为你带来魔力:)


1
投票

这是从csv文件中删除BOM的解决方案。

String localFilePath = "some_path_inputfile";
String localFilePath_Out = "some_path_outputfile";

    try (FileInputStream fis = new FileInputStream(new File(localFilePath));
         InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
         BufferedReader reader = new BufferedReader(isr);
         FileWriter writer = new FileWriter(localFilePath_Out)) {

        // Read the file and skip the BOM characters
        int firstChar = reader.read();
        if (firstChar != 0xFEFF) {
            // If the first character is not the BOM, write it to the output
            writer.write(firstChar);
        }

        int nextChar;
        while ((nextChar = reader.read()) != -1) {
            // Write the remaining characters to the output
            writer.write(nextChar);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

此后您可以使用输出文件,因为它没有 BOM。


0
投票

如果你不想写入文件并在内存中交换,你也可以使用流,对我来说,我只是重新创建了没有 BOM 的流

public static ByteArrayOutputStream removeBOM(InputStream is) {
    try {

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(os);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
        int firstChar = reader.read();
        if (firstChar != 0xFEFF) {
            writer.write(firstChar);
        }

        int nextChar;
        while ((nextChar = reader.read()) != -1) {
            writer.write(nextChar);
        }

        writer.close();
        return os;
    } catch (Exception e) {
        throw new BusinessException(ErrorBean.withError(Errors.FILE_TYPE, "Error parsing csv", ""));
    }
}

并用作

ByteArrayOutputStream os = removeBOM(file.getInputStream());
Inputstream is = new ByteArrayInputStream(bytes);

0
投票

我遇到了同样的问题。

对我来说最简单的解决方案是匹配所需的列名称(带或不带 BOM)。

@CsvBindByNames({@CsvBindByName(column = "Column name"), @CsvBindByName(column = "\uFEFFColumn name")})
private String name;
© www.soinside.com 2019 - 2024. All rights reserved.