Подсчет строк из CSV-файла - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь подсчитать количество r, t и c в приведенном ниже файле csv.

В настоящее время я возвращаю значения 4 c 0 и 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 голосов
/ 24 сентября 2018

Размещенный код не будет компилироваться, но эта строка:

while (br.readLine() != null)

читает строку, но не присваивает ее переменной, поэтому значение теряется.

Затем в пределахЗациклите эту строку:

line = br.readLine();  

читает следующую строку и присваивает ее переменной.Таким образом, каждая итерация по существу пропускает строку.

Измените условие цикла на:

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

, чтобы строка чтения была назначена переменной.И удалите это в цикле:

 line = br.readLine();  

, чтобы избежать пропуска строки.

Кроме того, вместо массива рассмотрите возможность использования Map<String, Integer> для отслеживания количества.

0 голосов
/ 24 сентября 2018

Предполагая, что ваш код является методом, в котором вы передаете letter в виде строки, тогда строка, в которой вы считаете букву, должна быть

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

НО, проблема и ошибка с вашим кодомявляется циклом for-sourding: Здесь вы посчитаете каждое вхождение буквы три раза.Удалите эти циклы for, поскольку они вам не нужны.

0 голосов
/ 24 сентября 2018

В вашем коде есть несколько проблем:

  • Используйте Scanner или BufferedReader, но не оба.
  • Вам нужно будет использовать цикл do-while, иначе первая строка будет пропущена.Здесь мы читаем каждую строку и затем переходим к чтению следующей строки.
  • Вы не проверяете, соответствует ли первый индекс массива 'r', 'c' или 't'.Если это соответствует, увеличивайте переменную count.
  • Вам не нужно вложенное 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;
}
0 голосов
/ 24 сентября 2018

Поскольку ваш код не компилируется, трудно сказать, что не так.Вот альтернативное решение для вашей проблемы:

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

Я буду рад помочь вам, но сделаю ваш код компилируемым, чтобы мы могли помочь вам отладитьit.

EDIT : более отказоустойчивая версия кода

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>

Edit 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
  • Убрано для цикла это было бесполезно
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...