加载CSV文件时过滤特定行

时间:2018-08-20 12:23:14

标签: java csv filter annotations opencsv

所以我有这个POJO类:

public class Player {

 @CsvBindByName
 private String simTime;

 @CsvBindByName
 private String playerId;

 @CsvBindByName
 private String dimX;

 @CsvBindByName
 private String offX;

 @CsvBindByName
 private String dimY;

 @CsvBindByName
 private String roadS;

 @CsvBindByName
 private String roadT;

 public String getSimTime() {     
    return simTime;
 }

 public void setSimTime(String simTime) {
    this.simTime = simTime;
 }

 public String getPlayerId() {
    return playerId;
 }

 public void setPlayerId(String playerId) {
    this.playerId = playerId;
 }

 public String getDimX() {
    return dimX;
 }

 public void setDimX(String dimX) {
    this.dimX = dimX;
 }

 public String getOffX() {
    return offX;
 }

 public void setOffX(String offX) {
    this.offX = offX;
 }

 public String getDimY() {
    return dimY;
 }

 public void setDimY(String dimY) {
    this.dimY = dimY;
 }

 public String getRoadS() {
    return roadS;
 }

 public void setRoadS(String roadS) {
    this.roadS = roadS;
 }

 public String getRoadT() {
    return roadT;
 }

 public void setRoadT(String roadT) {
    this.roadT = roadT;
 }

 @Override
 public String toString() {
    return "Player{" + "simTime=" + simTime + ", playerId=" + playerId + ", dimX=" + dimX + ", offX=" + offX + ", dimY=" + dimY + ", roadS=" + roadS + ", roadT=" + roadT + '}';
 }

}

我有一个很大的excel文件,其中有很多列。我的excel文件中的一列称为objectId

使用此代码:

private void loadCSVFiles() throws Exception {
    List<Player> beans = new CsvToBeanBuilder(new FileReader("C:\\Users\\noname\\Desktop\\ABP_S31\\ABP20180809_S31_FG_Notbremsung_100.csv"))
            .withType(Player.class)
            .withIgnoreLeadingWhiteSpace(true)
            .build()
            .parse();
    beans.forEach(System.out::println);

}

我设法获得了我需要的特定列。  我遇到的问题是,现在我只需要playerId等于objectId的行。显然,我可以将objectId添加为类属性,并且在加载文件后,可以遍历整个列表并再次过滤行。但是我不想这样

  1. 性能问题
  2. objectId实际上与我的Player类无关

我也可以加载整个excel文件并过滤列,但我也不希望这样做,因为就我个人而言,如果以当前方式执行此操作,则更具可读性。有没有办法解决这个问题,还是我必须使用上面的选项?

我尝试使用csvToBeanFilter,但不推荐使用getColumnIndex方法:docu

1 个答案:

答案 0 :(得分:0)

因此,如果您知道列标题,并且确定将来它们不会更改,则可以使用自定义CsvToBeanFilter来实现HeaderColumnNameMappingStrategy。这样,您可以避免使用不推荐使用的getColumnIndex()方法。

private class MyStrategy<T> implements HeaderColumnNameMappingStrategy<T> {

  private int playerIndex;
  private int objectIndex;

  @Override
  public void captureHeader(CSVReader reader) throws IOException {

    // make sure to call super() first because it will retrieve the header variable
    super();

    // inspect the header and store the relevant indices for later use
    for(int i = 0; i < header.length; i++)
    {
      if("objectId".equals(header[i])
        objectIndex = i;
      else if("playerId".equals(header[i])
        playerIndex = i;
    }
  }

  public int getPlayerIndex(){ return playerIndex; }
  public int getObjectIndex(){ return objectIndex; }
}

在过滤器中使用

private class MyFilter implements CsvToBeanFilter {

  private final MappingStrategy strategy;

  public MyFilter(MappingStrategy strategy) {
    this.strategy = strategy;
  }

  public boolean allowLine(String[] line) {
    // restore the relevant indices from the strategy
    int playerIndex = strategy.getPlayerIndex();
    int objectIndex = strategy.getObjectIndex();
    String playerId = line[playerIndex];
    String objectId = line[objectIndex];

    return playerId.equals(objectId);
  }
}

现在您可以将过滤器添加到CsvToBeanBuilder

private void loadCSVFiles() throws Exception {
  MappingStrategy strategy = new MyStrategy();
  List<Player> beans = new CsvToBeanBuilder(new FileReader("C:\\Users\\noname\\Desktop\\ABP_S31\\ABP20180809_S31_FG_Notbremsung_100.csv"))
          .withType(Player.class)
          .withIgnoreLeadingWhiteSpace(true)
          .withMapper(strategy)
          .withFilter(new MyFilter())
          .build()
          .parse();
  beans.forEach(System.out::println);

}