Calculating Average from a CSV File

2019-02-27 04:33发布

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.

标签: java csv average
4条回答
仙女界的扛把子
2楼-- · 2019-02-27 05:09

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
}
查看更多
疯言疯语
3楼-- · 2019-02-27 05:15

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.

查看更多
萌系小妹纸
4楼-- · 2019-02-27 05:15

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) {
查看更多
地球回转人心会变
5楼-- · 2019-02-27 05:26

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();
查看更多
登录 后发表回答