How to read and parse CSV file in Java

country-csv-example

A Comma-Separated Values (CSV) file is just a normal plain-text file, store data in column by column, and split it by a separator (e.g normally it is a comma “,”).

For example :

1,US,United States
2,MY,Malaysia
3,AU,Australia

or

"1","US","United States"
"2","MY","Malaysia"
"3","AU","Australia"
Note
Read this RFC4180 document for Comma-Separated Values (CSV) format.

In a CSV file, normally there are two issues:

1. The field containing separator, for example, separator is a comma, and the field containing commas:

"aaa","b,bb","ccc"

2. The double-quotes are used to enclose fields, and the field containing double-quotes. To solve it, a double-quote appearing inside a field must be escaped by preceding it with another double quote (RFC4180)

"aaa","b""bb","ccc"

In this tutorial, we show you three examples to read, parse and print out the values from a CSV file.

  1. Simple solution to parse a simple formatted CSV file.
  2. Advance solution to parse a weird formatted CSV file (field containing separator or double-quotes)
  3. Third party solution, OpenCSV example.

1. Simple Solution

If you are sure the CSV files doesn’t contain “separator or double-quotes”, just use the standard split() to parse the CSV file.

1.1 Review a simple CSV file

/Users/mkyong/csv/country.csv
"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"

1.2 No magic, just read above text file, and splits it by a comma separator.

CSVReader.csv

package com.mkyong.csv;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country.csv";
        BufferedReader br = null;
        String line = "";
        String cvsSplitBy = ",";

        try {

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

                // use comma as separator
                String[] country = line.split(cvsSplitBy);

                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

}

1.3 For JDK 7 and above, uses try-resources.

CSVReader.csv

package com.mkyong.csv;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country.csv";
        String line = "";
        String cvsSplitBy = ",";

        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

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

                // use comma as separator
                String[] country = line.split(cvsSplitBy);

                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Output

Country [code= "AU" , name="Australia"]
Country [code= "CN" , name="China"]
Country [code= "AU" , name="Australia"]
Country [code= "CN" , name="China"]
Country [code= "JP" , name="Japan"]
Country [code= "CN" , name="China"]
Country [code= "JP" , name="Japan"]
Country [code= "TH" , name="Thailand"]

2. Advance Solution

This solution will solve the field containing “separator or double-quotes” issue, and also support the custom separator and custom enclosed field. Review the following CSV parsing example and also the JUnit test cases to understand how it works.

Note
Again, if a double-quote appearing inside a field must be escaped by preceding it with another double quote, for example

"aaa","b""bb","ccc"

2.1 Review another CSV file

/Users/mkyong/csv/country2.csv
10,AU,Australia
11,AU,Aus""tralia
"12","AU","Australia"
"13","AU","Aus""tralia"
"14","AU","Aus,tralia"

2.2 The below example is inspired by this article – “Only Class You Need for CSV Files” (with some fixed to support other features, read “fixed comments”) and also this third party OpenCSV library.

CSVUtils.java

package com.mkyong.utils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CSVUtils {

    private static final char DEFAULT_SEPARATOR = ',';
    private static final char DEFAULT_QUOTE = '"';

    public static void main(String[] args) throws Exception {

        String csvFile = "/Users/mkyong/csv/country2.csv";

        Scanner scanner = new Scanner(new File(csvFile));
        while (scanner.hasNext()) {
            List<String> line = parseLine(scanner.nextLine());
            System.out.println("Country [id= " + line.get(0) + ", code= " + line.get(1) + " , name=" + line.get(2) + "]");
        }
        scanner.close();

    }

    public static List<String> parseLine(String cvsLine) {
        return parseLine(cvsLine, DEFAULT_SEPARATOR, DEFAULT_QUOTE);
    }

    public static List<String> parseLine(String cvsLine, char separators) {
        return parseLine(cvsLine, separators, DEFAULT_QUOTE);
    }

    public static List<String> parseLine(String cvsLine, char separators, char customQuote) {

        List<String> result = new ArrayList<>();

        //if empty, return!
        if (cvsLine == null && cvsLine.isEmpty()) {
            return result;
        }

        if (customQuote == ' ') {
            customQuote = DEFAULT_QUOTE;
        }

        if (separators == ' ') {
            separators = DEFAULT_SEPARATOR;
        }

        StringBuffer curVal = new StringBuffer();
        boolean inQuotes = false;
        boolean startCollectChar = false;
        boolean doubleQuotesInColumn = false;

        char[] chars = cvsLine.toCharArray();

        for (char ch : chars) {

            if (inQuotes) {
                startCollectChar = true;
                if (ch == customQuote) {
                    inQuotes = false;
                    doubleQuotesInColumn = false;
                } else {

                    //Fixed : allow "" in custom quote enclosed
                    if (ch == '\"') {
                        if (!doubleQuotesInColumn) {
                            curVal.append(ch);
                            doubleQuotesInColumn = true;
                        }
                    } else {
                        curVal.append(ch);
                    }

                }
            } else {
                if (ch == customQuote) {

                    inQuotes = true;

                    //Fixed : allow "" in empty quote enclosed
                    if (chars[0] != '"' && customQuote == '\"') {
                        curVal.append('"');
                    }

                    //double quotes in column will hit this!
                    if (startCollectChar) {
                        curVal.append('"');
                    }

                } else if (ch == separators) {

                    result.add(curVal.toString());

                    curVal = new StringBuffer();
                    startCollectChar = false;

                } else if (ch == '\r') {
                    //ignore LF characters
                    continue;
                } else if (ch == '\n') {
                    //the end, break!
                    break;
                } else {
                    curVal.append(ch);
                }
            }

        }

        result.add(curVal.toString());

        return result;
    }

}

Output

Country [id= 10, code= AU , name=Australia]
Country [id= 11, code= AU , name=Aus"tralia]
Country [id= 12, code= AU , name=Australia]
Country [id= 13, code= AU , name=Aus"tralia]
Country [id= 14, code= AU , name=Aus,tralia]

3.3 Review the following unit test, it test the “commas and double quotes” issue.

CSVUtilsTest.java

package com.mkyong.csv;

import com.mkyong.utils.CSVUtils;
import org.hamcrest.core.IsNull;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class CSVUtilsTest {

    @Test
    public void test_no_quote() {

        String line = "10,AU,Australia";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_no_quote_but_double_quotes_in_column() throws Exception {

        String line = "10,AU,Aus\"\"tralia";

        List<String> result = CSVUtils.parseLine(line);
        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

    @Test
    public void test_double_quotes() {

        String line = "\"10\",\"AU\",\"Australia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_double_quotes_but_double_quotes_in_column() {

        String line = "\"10\",\"AU\",\"Aus\"\"tralia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

    @Test
    public void test_double_quotes_but_comma_in_column() {

        String line = "\"10\",\"AU\",\"Aus,tralia\"";
        List<String> result = CSVUtils.parseLine(line);

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus,tralia"));

    }

}

3.4 Review another unit test, it test the custom separator and custom enclosed field.

CSVUtilsTestCustom.java

package com.mkyong.csv;

import com.mkyong.utils.CSVUtils;
import org.hamcrest.core.IsNull;
import org.junit.Test;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class CSVUtilsTestCustom {

    @Test
    public void test_custom_separator() {

        String line = "10|AU|Australia";
        List<String> result = CSVUtils.parseLine(line, '|');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_custom_separator_and_quote() {

        String line = "'10'|'AU'|'Australia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Australia"));

    }

    @Test
    public void test_custom_separator_and_quote_but_custom_quote_in_column() {

        String line = "'10'|'AU'|'Aus|tralia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus|tralia"));

    }

    @Test
    public void test_custom_separator_and_quote_but_double_quotes_in_column() {

        String line = "'10'|'AU'|'Aus\"\"tralia'";
        List<String> result = CSVUtils.parseLine(line, '|', '\'');

        assertThat(result, IsNull.notNullValue());
        assertThat(result.size(), is(3));
        assertThat(result.get(0), is("10"));
        assertThat(result.get(1), is("AU"));
        assertThat(result.get(2), is("Aus\"tralia"));

    }

}

3. OpenCSV Example

If you are not comfortable with above simple and advance solution, try using third party CSV library – OpenCSV.

3.1 Maven.

pom.xml

	<dependency>
		<groupId>com.opencsv</groupId>
		<artifactId>opencsv</artifactId>
		<version>3.8</version>
	</dependency>

3.2 Review a CSV file.

/Users/mkyong/csv/country3.csv
10,AU,Australia
11,AU,Aus""tralia
"12","AU","Australia"
"13","AU","Aus""tralia"
"14","AU","Aus,tralia"

3.2 OpenCSV example to parse above CSV file.

CSVReaderExample.java

package com.mkyong.csv;

import com.opencsv.CSVReader;

import java.io.FileReader;
import java.io.IOException;

public class CSVReaderExample {

    public static void main(String[] args) {

        String csvFile = "/Users/mkyong/csv/country3.csv";

        CSVReader reader = null;
        try {
            reader = new CSVReader(new FileReader(csvFile));
            String[] line;
            while ((line = reader.readNext()) != null) {
                System.out.println("Country [id= " + line[0] + ", code= " + line[1] + " , name=" + line[2] + "]");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

}

Output

Country [id= 10, code= AU , name=Australia]
Country [id= 11, code= AU , name=Aus"tralia]
Country [id= 12, code= AU , name=Australia]
Country [id= 13, code= AU , name=Aus"tralia]
Country [id= 14, code= AU , name=Aus,tralia]
Note
Please refer to this OpenCSV official documentation for more examples.

Done.

References

  1. The Only Class You Need for CSV Files
  2. CSVHelper Example
  3. Ostermiller Java Utilities – Comma Separated Values (CSV)
  4. RFC4180 – Format for Comma-Separated Values (CSV)
  5. OpenCSV website
  6. Java – How to export data to CSV file

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
ziggyfish
Guest
ziggyfish

Hi,

You have an error in your code:

//if empty, return!

if (cvsLine == null && cvsLine.isEmpty()) {

return result;

}

should be:

//if empty, return!

if (cvsLine == null || cvsLine.isEmpty()) {

return result;

}

JacksonImplementer
Guest
JacksonImplementer

Hallo Mkyong,

Your articles are really interesting to read every time. Will the CSV parser work if my object has object as member variable?.

for example
public class {
int modelNumber;
String modelName;
CarDefination carDefin;
}

what happens if there are Object as member variable?

Ömer Hakan Bilici
Guest
Ömer Hakan Bilici

Thanks. Note that OpenCSV Example part is enough for most cases. I think you should move this part to start of this post.

GiladD
Guest
GiladD

Great article. Thanks! However, there is an error in the following line in your CSVUtils:
if (cvsLine == null && cvsLine.isEmpty()) {
The two conditions can’t co-exist. If csvLine is null then isEmpty will throw a NullPointerException.
It should be:
if (cvsLine == null || cvsLine.isEmpty()) {

Works great beside that!

Apercova
Guest
Apercova
HI!. I have test case that is not cover by your advanced solution: I have the following csv line: String line = “10,”AU”,”Aus””tralia””; Your solution outputs the next: 10, “AU, “Aus””tralia You can se that a quote is appended to the value AU and to Aus””tralia this behavior is caused in this part: //Fixed : allow “” in empty quote enclosed if (chars[0] != ‘”‘ && customQuote == ‘”‘) { curVal.append(‘”‘); } I wonder what scenario is this fix for, because if I comment this code the csv line is parsed fine.
code date
Guest
code date
package take; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; public class DateUtil { // List of all date formats that we want to parse. // Add your own format here. private static List dateFormats = new ArrayList() { private static final long serialVersionUID = 1L; { add(new SimpleDateFormat(“M/dd/yyyy”)); add(new SimpleDateFormat(“dd.M.yyyy”)); add(new SimpleDateFormat(“M/dd/yyyy hh:mm:ss a”)); add(new SimpleDateFormat(“dd.M.yyyy hh:mm:ss a”)); add(new SimpleDateFormat(“dd.MMM.yyyy”)); add(new SimpleDateFormat(“dd-MMM-yyyy”)); } }; /** * Convert String with various formats into java.util.Date * * @param input * Date as a string * @return java.util.Date object if input string is parsed * successfully else returns null */… Read more »
Hsiwei
Guest
Hsiwei

Thanks.
It’s useful.

Sourov
Guest
Sourov

Some cells of my CSV file contain unquoted multiple comma like 187,859,049. After splitting by comma it returns 187. But I need 187,859,049. Can anyone say, how to solve this?

Cheikhna
Guest
Cheikhna

Thanks for this example, So now how can i add this data in database without using springbatch. just use java and maven project

Areizero Developer
Guest
Areizero Developer

Nice, OpenCSV really work very well

Ria
Guest
Ria

hi how can I ignore “” in this kind of statement?
blabla,blabla,”Blabla,blabla”,bla

while I m using the BufferReader

Anant
Guest
Anant

My Java object MyObject has 3 properties:
DepartmentName, Location, list
where Employee has Name, id, age
my csv is
Department_name,Location,Name,ID,AGE
IT,BLR,Anant,1,29
IT,BLR,Akshay,2,49
IT,BLR,Aditi,3,30
IT,BLR,Ram,4,29
HR,Pune,Amit,22,55
HR,Pune,aa,22,55
HR,Pune,ee,22,55
HR,Pune,er4,22,55

In this case I need the MyObj which should have department list and department should have employee list. How to achieve this.

peter valencic
Guest
peter valencic

Thank you!

Kishore Ramineni
Guest
Kishore Ramineni

Hi Mkyong,
Is there a way to write data at desired positions in the Csv

Sarah Ahmed
Guest
Sarah Ahmed

kindly i need to know how to read csv file from input stream

Äbbäs MüJähid
Guest
Äbbäs MüJähid

If i have a text at top and after that i have data then how i can read header and data separatly??

mkyong
Guest
mkyong

Read the file and skip the first line (header)

Aravind Selvaraj
Guest
Aravind Selvaraj

I am new to java when i execute it shows the error message like this

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 4

at ReadCVS.run(ReadCVS.java:30)

at ReadCVS.main(ReadCVS.java:11)

help me !!

mkyong
Guest
mkyong

Article is updated, please try again.

Naresh
Guest
Naresh

May i know file path declaration example please

ramu
Guest
ramu

if any one knows how to down load a file from server pls help me

ramu
Guest
ramu
Hi, in my Project i have to read csv file by downloading it from server .i’m also using code like public class ReadCVS { public static void main(String[] args) { ReadCVS obj = new ReadCVS(); obj.run(); } public void run() { String csvFile = “/Users/mkyong/Downloads/GeoIPCountryWhois.csv”; BufferedReader br = null; String line = “”; String cvsSplitBy = “,”; try { Map maps = new HashMap(); br = new BufferedReader(new FileReader(csvFile)); while ((line = br.readLine()) != null) { // use comma as separator String[] country = line.split(cvsSplitBy); maps.put(country[4], country[5]); } //loop map for (Map.Entry entry : maps.entrySet()) { System.out.println(“Country [code= ” +… Read more »
shady shrif
Guest
shady shrif

I think it would be better if you used

http://sourceforge.net/projects/opencsv/

tsktsk
Guest
tsktsk

readline doesn’t work if there are carriage return chars in data.

MKP
Guest
MKP

Thanks Mr.Mkyong, its highly helpful.

Aamya Aman
Guest
Aamya Aman

helloo sir ,

i want to do file handling of parsed XML file ?

How i will do ?
Can you help me to solve this concept ?

Manju
Guest
Manju

Hi Mkyong,

I’ve been given with a task to accept a csv file from UI (say a jsp form using file tag), parse the data of that file into beans, and output a csv file with a ‘Success’ message with respect to every file item. I’m new to java and I dont know how exactly to handle this. Can you please suggest any ideas that can help me doing this?

nickelen
Guest
nickelen

Hi, mkyong,

I think it’s better to use

String[] country = line.split(cvsSplitBy, -1);

because in many cases, csv file contains one line with empty value at the end just like:

“1.0.64.0”,”1.0.127.255″,”16793600″,”16809983″,”JP”,”Japan”,,,,,

line.split(cvsSplitBy) will get an array length = 6, but most time we expect to get correct array which length is containing empty values at the end.

What do you think ?

mkyong
Guest
mkyong

Thanks for your input. Yes, your way is better.

mayur
Guest
mayur

If your value in column contains comma , then this logics failed

mkyong
Guest
mkyong

Article is updated to support field containing separator (comma).

grewaljimmy
Guest
grewaljimmy

br = new BufferedReader(new FileReader(csvFile)); plz explain this line in detail

mlimbu
Guest
mlimbu

Hello mkyoung, doesn’t the country string array get overwritten with newer data as the reader retrieves newer lines from the text file? I am experiencing similar problem. A new record in my text file is overwriting the previous indexes in the string array.

Hit Chikani
Guest
Hit Chikani

hello,
i want to export and import Call Log In CSV file in My SD Card. so please help me

nea
Guest
nea
package net.viralpatel.java; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import au.com.bytecode.opencsv.CSVReader; public class Main { public static void main(String[] args) { try { CSVLoader loader = new CSVLoader(getCon()); loader.loadCSV(“C:\Users\NTANWAR\Desktop\std_db.csv”, “student_db”, true); } catch (Exception e) { e.printStackTrace(); } } private static Connection getCon() throws SQLException { Connection connection = null; try { String driver = “com.mysql.jdbc.Driver”; Class.forName(driver); String url = “jdbc:mysql://localhost:3306/”; String dbName = “demo”; String userName = “root”; String password = “root”; connection = DriverManager.getConnection(url+dbName,userName,password); } catch (ClassNotFoundException e) { e.printStackTrace(); } return connection; } }