Calculating Average from a CSV File

一世执手 提交于 2019-12-20 02:54:07

问题


I have a CSV file, format as follows:

City,Job,Salary Delhi,Doctors,500 Delhi,Lawyers,400 Delhi,Plumbers,100 London,Doctors,800 London,Lawyers,700 London,Plumbers,300 Tokyo,Doctors,900 Tokyo,Lawyers,800 Tokyo,Plumbers,400 Lawyers,Doctors,300 Lawyers,Lawyers,400 Lawyers,Plumbers,500 Hong Kong,Doctors,1800 Hong Kong,Lawyers,1100 Hong Kong,Plumbers,1000 Moscow,Doctors,300 Moscow,Lawyers,200 Moscow,Plumbers,100 Berlin,Doctors,800 Berlin,Plumbers,900 Paris,Doctors,900 Paris,Lawyers,800 Paris,Plumbers,500 Paris,Dog catchers,400

I want to find the average of the total salaries.

This is my code:

` import java.io.*;

public class A {

public static void main(String args[])
{
A a= new A();
a.run();
}

public void run()
{
String csv="C:\\Users\\Dipayan\\Desktop\\salaries.csv";
        BufferedReader br = null;
String line = "";
int sum=0;
int count=0;
//String a=new String();


        try {

            br = new BufferedReader(new FileReader(csv));
            try {
                while ((line = br.readLine()) != null) {

                        // use comma as separator
                    String[] country = line.split(",");
                    int sal=Integer.parseInt(country[2]);
                    sum=sum+sal;
                         count++;
                //System.out.println("Salary [job= " + country[0] 
                                  //        + " , salary=" + country[2] + "]");

                }
            } catch (NumberFormatException | IOException e) {
                System.out.println("NA");
                e.printStackTrace();
            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }  
        System.out.println(sum/count);


        System.out.println("Done");
      }

    }` 

But, its showing error:

java.lang.NumberFormatException: For input string: "Salary" at java.lang.NumberFormatException.forInputString(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at java.lang.Integer.parseInt(Unknown Source) at A.run(A.java:30) at A.main(A.java:9) Exception in thread "main" java.lang.ArithmeticException: / by zero at A.run(A.java:46) at A.main(A.java:9)`

Is there any better or short code to parse the CSV file.


回答1:


Skip the first line of the CSV file. Do an additional

br.readLine()

before the while.

You might also want to add some format checks to be sure the file you are reading is in the correct format.




回答2:


The first line contains the word "Salary" in the third spot. Put br.readLine()before the loop and everything should be fine.

You have:

br = new BufferedReader(new FileReader(csv));
try {
  while ((line = br.readLine()) != null) {

Change it to:

br = new BufferedReader(new FileReader(csv));
br.readLine()
try {
  while ((line = br.readLine()) != null) {



回答3:


br.readLine() before the while-loop will avoid header line problem, but if your data is not correct you will get same Exception again, so, in order to make a safer method you can change this line:

int sal=Integer.parseInt(country[2]);

With a try-catch block to iterate through entire file even if a value is not a valid number

int sal;
try {
    sal=Integer.parseInt(country[2]);
} catch (NumberFormatException e) {
    // if you want here you can show an error message 
    // to give feedback to the user there is not a valid number
}



回答4:


First, use a CSV parser - I will use OpenCSV in this example. I have no affiliation with OpenCSV, it's just what I have in my POM at the moment.

First, create a class:

public class Salary {
    private String city;
    private String job;
    private long salary;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public long getSalary() {
        return salary;
    }

    public void setSalary(long salary) {
        this.salary = salary;
    }
}

Now your CSV has three columns, and the header of the CSV matches the property names of our bean, so we can simply use a HeaderColumnNameMappingStrategy to determine which properties to set on the bean:

final HeaderColumnNameMappingStrategy<Salary> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(Salary.class);

Now we just need to parse the CSV file into a List of our beans:

final CsvToBean<Salary> csvToBean = new CsvToBean<>();
try (final Reader reader = ...) {
    final List<Salary> salaries = csvToBean.parse(mappingStrategy, reader);
}

Okay.

Now, how do you get an average salary from this mess? Just use a Java 8 Stream on the result:

    final LongSummaryStatistics statistics = salaries.stream()
            .mapToLong(Salary::getSalary)
            .summaryStatistics();

Now we can get all sorts of useful information:

final long min = statistics.getMin();
final double average = statistics.getAverage();
final long max = statistics.getMax();


来源:https://stackoverflow.com/questions/29802763/calculating-average-from-a-csv-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!