【问题标题】:How to capture the field values in the csv file using bufferedreader如何使用 bufferedreader 捕获 csv 文件中的字段值
【发布时间】:2021-03-09 23:47:31
【问题描述】:

csv 文件看起来像这样

我正在尝试获取名称等字段值,它是 $$NAME$$ 之后的值(标识符后面有一个空格)。如何在 Java 中使用 BufferedReader 存储每个字段的值?字段可以是任意行号,不固定位置或格式,如果有特殊字符或遇到空值也会抛出错误。

      int n = 100; // Max lines
              String line;
              try (BufferedReader br = new BufferedReader(new FileReader(str)))
               {
                   while ((line = br.readLine()) != null && i++ < n)
                {
                      br.readLine();
                  line = br.readLine();
                  System.out.println(line);
                 }
               }

从 CSV 文件中提取值后,我需要将它们存储在一个字符串变量中,然后使用它为每个列值插入到数据库中

案例 2:对于最后一个字段 $$GROUP$$ CATEGORY,单元格 9 到 11 中的值是“5”,我需要匹配数据库中的列 CATEGORY 必须是 5 存储在一个字符串中被插入到同名的数据库列中。 当我使用 line.matches 条件时,正则表达式不会找到完全匹配

【问题讨论】:

  • 为什么需要确定Max lines?字段是否重复,即$$NAME$$ 是否多次出现?每一行是否仅包含您在示例中编写的内容,或者文件的每一行中是否还有其他值? $$WEATHER$$ 之后的文件中是否还有空格?你想如何存储字段值?您想将它们存储在ArrayList 之类的数据结构中,还是将它们写入另一个文件或将它们插入数据库?
  • 字段不重复,我提到最大行只是因为我不想遍历 csv 中的所有行,因为我相信必填字段必须在前 100 行之前位于顶部。每个行只有我提到的值,是的,在 $$WEATHER$$(space) 之后有一个空格,我更喜欢将提取的值存储在一个字符串中,以作为列值插入到数据库表中

标签: java regex string csv talend


【解决方案1】:

您可以在此处使用正则表达式来检测名称行:

int n = 100; // Max lines
String line;
try (BufferedReader br = new BufferedReader(new FileReader(str))) {
    while ((line = br.readLine()) != null && i++ < n) {
        if (line.matches("\\$\\$NAME\\$\|$.$")) {
            System.out.println(line.split(" ")[1]);
        }
    }
}

【讨论】:

  • 它不会匹配并且不会进入 if 循环(正则表达式)以匹配和提取值 if (line.contains("\\$\\$NAME\\$\\$.$ ")) { System.out.println(line.split(" ")[1]);我尝试使用 line.contains 仍然无法匹配名为 $$NAME$$ 的 csv 字段 ...最后一个 $ 之后有一个空格,尽管使用 .(匹配 0 个或更多字符) 它不会获取值?
【解决方案2】:

我建议你先用空格分割行,然后你会得到类似的东西 $$NAME$$,约翰。然后检索美元符号之间的密钥。

一个基于你的 sn-p 的例子:

int i = 0;
int n = 100; // Max lines
String line;
try (BufferedReader br = new BufferedReader(new FileReader(str))) {
  while ((line = br.readLine()) != null && i++ < n) {
    String[] splitLine = line.split(" ");
    String key = splitLine[0].split("\\$\\$")[1];
    String value = splitLine[1];
    System.out.printf("Name: %s | Value: %s%n", key, value);
  }
}

您还可以使用更现代的方法来使用 Java 9 文件 API 和流,这是一个示例:

  public static void main(String[] args) throws IOException, URISyntaxException {

    Path filePathFromProjectFolder = Path.of(ClassLoader.getSystemResource("file.csv").toURI());
    Map<String, String> csvValues = Files.readAllLines(filePathFromProjectFolder).stream()
        .map(line -> line.split(" "))
        .collect(Collectors.toMap(line -> getKeyName(line[0]), line -> line[1]));

    System.out.println(csvValues);
  }


  private static String getKeyName(String str) {
    return str.split("\\$\\$")[1];
  }

【讨论】:

    【解决方案3】:

    以下代码将仅读取文件的前 100 行并将值提取到列表中。

    java.nio.file.Path path = java.nio.file.Paths.get(str);
    try {
        java.util.List<String> values = java.nio.file.Files.lines(path)
                                                           .limit(100)
                                                           .filter(line -> line.matches("\\$\\$[A-Z]+\\$\\$ [0-9A-Z]*$"))
                                                           .map(line -> {
                                                               String[] words = line.split(" ");
                                                               return words.length == 2 ? words[1] : "";
                                                           })
                                                           .collect(java.util.stream.Collectors.toList());
        System.out.println(values);
    }
    catch (java.io.IOException xIo) {
        xIo.printStackTrace();
    }
    

    根据您问题中的示例文件,上述代码将创建以下列表。

    [JOHN, CA, SF, XYZ, , 25, CATEGORY, ]
    

    如果您想要Map 而不是List,其中Map 键是两个$ 字符之间的值,而Map 值是空格后面的部分,那么

    Function<String, String> keyMapper = line -> {
        String[] parts = line.split(" ");
        return parts[0].substring(2, parts[0].length() - 2);
    };
    Function<String, String> valueMapper = line -> {
        String[] parts = line.split(" ");
        if (parts.length > 1) {
            return parts[1];
        }
        else {
            return "";
        }
    };
    Path path = Paths.get(str);
    try {
        Map<String, String> map = Files.lines(path)
                                       .limit(100)
                                       .filter(line -> line.matches("\\$\\$[A-Z]+\\$\\$ [0-9A-Z]*$"))
                                       .collect(Collectors.toMap(keyMapper, valueMapper));
        System.out.println(map);
    }
    catch (IOException xIo) {
        xIo.printStackTrace();
    }
    

    这将创建以下Map

    {GROUP=CATEGORY, WEATHER=, CITY=SF, STATE=CA, TIME=, NAME=JOHN, REGION=XYZ, AGE=25}
    

    【讨论】:

      猜你喜欢
      • 2017-04-02
      • 2016-04-16
      • 1970-01-01
      • 2016-08-30
      • 2012-06-08
      • 2011-08-11
      • 1970-01-01
      • 2017-04-22
      • 1970-01-01
      相关资源
      最近更新 更多