繁体   English   中英

计数csv文件中的行

[英]Counting lines from a csv file

我正在尝试在下面的csv文件中计算r,t和c的数量。

我目前正在返回值4 c's 0 r's和3 t's,这不是准确的结果。 有人可以帮助我识别代码中的错误吗?

public static int getCount ( String fileName, String letter )
{
int count = 0;
String line;
String[] lineArray new String[3];  
Scanner sc = new Scanner (System.in);  
try  
{  
    BufferedReader br = new BufferedReader(new FileReader(fileName));  
    count = 0;  
    while (br.readLine() != null)  
    {  
        line = br.readLine();  
        lineArray = line.split(",");  
        for (int i = 0; i < lineArray.length; i++)  
        {  
(lineArray[0].equals(letter))count++;  
        }  
    }  
    br.close();  
}  
return count;  
}

我正在读取一个csv文件。

r,21.2,12.2  
c,50  
t,23.4,56.8  
t,15.3,12.2  
c,32  
t,32.3,23.5  

发布的代码将无法编译,但以下行:

while (br.readLine() != null)

读取一行,但未将其分配给变量,因此该值会丢失。

然后在循环中此行:

line = br.readLine();  

读取下一行并将其分配给变量。 因此,每次迭代实质上都会跳过一行。

将循环条件更改为:

while ((line = br.readLine()) != null)

因此将读取行分配给变量。 并在循环中删除它:

 line = br.readLine();  

避免跳过一行。

另外,考虑使用Map<String, Integer>而不是数组来跟踪计数。

由于您的代码无法编译,因此很难说出问题所在。 这是您的问题的替代解决方案:

public static void main(String[] args) {
    try {
        Map<String, Long> csvOccurences = Files.readAllLines(Paths.get("text.csv"))
            .stream()
            .map(csvLine -> csvLine.split(",")[0])
            .collect(Collectors.groupingBy(csvLine -> csvLine, Collectors.counting()));

        System.out.println("c occurence -> "  + csvOccurences.getOrDefault("c", 0L));
        System.out.println("t occurence -> "  + csvOccurences.getOrDefault("t", 0L));
        System.out.println("z occurence -> "  + csvOccurences.getOrDefault("z", 0L));

    } catch (Exception exception) {
        System.err.print("Unable to elaborate the csv");
        exception.printStackTrace();
    }
}

代码输出:

c occurence -> 2
t occurence -> 3
z occurence -> 0

我很乐意为您提供帮助,但使您的代码可编译,因此我们可以帮助您调试它。

编辑 :该代码的更多故障安全版本

Map<String, Long> csvOccurences =
                Files.readAllLines(Paths.get("text.csv"))   // Read the files and get all the lines
                .stream()                                   // Iterate all the lines
                .map(csvLine -> csvLine.split(","))         // Split the line into tokens (split by ',')
                .filter(csvTokens -> csvTokens.length >= 1) // Filter out all the lines that don't have at least 2 tokens
                .map(csvTokens -> csvTokens[0])             // Map the stream to only the first token
                .map(String::trim)                          // Trim the string (remove the space at start and at the end)
                .filter(csvToken -> csvToken.length() == 1) // Filter out all the token that have more than one letter (is this necessary?)
                .collect(Collectors.groupingBy(csvLine -> csvLine, Collectors.counting())); // Count the occurence of each letter and map them Map<Letter, Occurence>

编辑2,您的方法已修复并重构:

public static int getCount(String fileName, String letter) throws Exception {
    // Put the stream inside the try/catch so they get closed automatically
    try (FileReader fileReader = new FileReader(fileName);
         BufferedReader bufferReader = new BufferedReader(fileReader)) {
        // Initialized the counter to 0
        int letterCount = 0;
        // Declare a line buffer
        String lineBuffer;
        // While readLine is not returning null put the line inside lineBuffer
        while ((lineBuffer = bufferReader.readLine()) != null) {
            // Split the line buffer into tokens
            String[] lineTokens = lineBuffer.split(",");
            // If the tokens are more than 0 and the first token is equal to the letter
            if (lineTokens.length > 0 && lineTokens[0].equals(letter)) {
                // Increment the letter count
                letterCount++;
            }
        }
        // Return the letter count
        return letterCount;
    }
}

所采取的行动:

  • 重命名变量
  • 在try-catch中移动了流(BufferedReader / FileReader)
  • 删除了Scanner sc = new Scanner (System.in); 这没用
  • 添加了对数组lineTokens.length > 0的长度的检查
  • 删除了无用的for循环

假设您的代码是一种将letter作为字符串移交的方法,那么计算字母的行必须是

if (lineArray[0].equals(letter)) count++;

但是,代码的问题和错误是环绕的for循环:在这里,您将字母的每次出现数计算三次。 删除这些for循环,因为您不需要它。

您的代码中存在多个问题:

  • 使用ScannerBufferedReader ,不能两者都使用。
  • 您需要使用do-while循环,否则第一行将被跳过。 在这里,我们阅读每一行,然后继续阅读下一行。
  • 您不检查数组的第一个索引是否匹配“ r”,“ c”或“ t”。 如果匹配,则增加计数变量。
  • 在拆分和解析每一行时,您不需要嵌套的for-loop

== ==代码

   public static int findCount(String fileName) {
       int count = 0;
       String[] lineArray = new String[3];
       try {
            Scanner br = new Scanner(new FileReader(fileName));

             do {
                lineArray = br.nextLine().split(",");
                if (lineArray[0].matches("c|r|t")) {
                    count++;
                }
             } while (br.hasNextLine());

             br.close();
        } catch (Exception e) {
          // handle exception   
          e.printStackTrace();
        }   

       return count;       
   }

使用Java-8,我们可以一行完成全部操作。

public static long getCount(String fileName) {
    try {
        return Files.readAllLines(Paths.get(fileName)).stream().map(line -> line.split(",")[0])
                .filter(str -> str.matches("c|r|t")).count();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM