计算csv文件中的行数

时间:2018-09-24 13:13:37

标签: java file loops csv

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

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

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  

4 个答案:

答案 0 :(得分:2)

发布的代码无法编译,但此行:

while (br.readLine() != null)

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

然后在循环中显示以下行:

line = br.readLine();  

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

将循环条件更改为:

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

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

 line = br.readLine();  

为避免跳过一行。

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

答案 1 :(得分:1)

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

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;
    }
}

已采取的措施:

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

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

  • 同时使用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;
}