Java IO Tutorial

How to write data to CSV file in Java

Java write data to csv file

This article shows how to write data to a comma-separated values (CSV) file.

Topics:

  1. OpenCSV – Write data to a CSV file
  2. Single class CSV writer – Write data to a CSV file
  3. Single class CSV writer – Unit Tests

Note
The RFC 4180 defines the format or definitions of a CSV file or text/csv file.

1. OpenCSV – Write data to CSV file

1.1 The OpenCSV is a easy to use CSV Parser and Writer.

pom.xml

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

1.2 This OpenCSV example uses CSVWriter to write a List<String[]> to a file.

OpenCsvWriterExample.java

package com.mkyong.io.csv.opencsv;

import com.opencsv.CSVWriter;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class OpenCsvWriterExample {

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

        List<String[]> csvData = createCsvDataSimple();

        // default all fields are enclosed in double quotes
        // default separator is a comma
        try (CSVWriter writer = new CSVWriter(new FileWriter("c:\\test\\test.csv"))) {
            writer.writeAll(csvData);
        }

    }

    private static List<String[]> createCsvDataSimple() {
        String[] header = {"id", "name", "address", "phone"};
        String[] record1 = {"1", "first name", "address 1", "11111"};
        String[] record2 = {"2", "second name", "address 2", "22222"};

        List<String[]> list = new ArrayList<>();
        list.add(header);
        list.add(record1);
        list.add(record2);

        return list;
    }

}

Review the newly created CSV file. By default, all fields are enclosed in double-quotes, and the default separator is a comma.

c:\\test\\test.csv

"id","name","address","phone"
"1","first name","address 1","11111"
"2","second name","address 2","22222"

1.3 This OpenCSV example shows the use of custom separator, semicolon ;.


  try (ICSVWriter writer = new CSVWriterBuilder(
          new FileWriter("c:\\test\\test.csv"))
          .withSeparator(';')
          .build()) {
      writer.writeAll(csvData);
  }

Output

c:\\test\\test.csv

"id";"name";"address";"phone"
"1";"first name";"address 1";"11111"
"2";"second name";"address 2";"22222"

1.4 This OpenCSV example test the common embedded issues in CSV files – embedded comma, double quotes and line breaks. Read RFC 4180.

OpenCsvWriterExample.java

package com.mkyong.io.csv.opencsv;

import com.opencsv.CSVWriter;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class OpenCsvWriterExample {

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

        List<String[]> csvData = createCsvDataSpecial();

        // default all fields are enclosed in double quotes
        // default separator is a comma
        try (CSVWriter writer = new CSVWriter(new FileWriter("c:\\test\\monitor.csv"))) {
            writer.writeAll(csvData);
        }

    }

    private static List<String[]> createCsvDataSpecial() {

        String[] header = {"Make", "Model", "Description", "Price"};
        String[] record1 = {"Dell", "P3421W", "Dell 34, Curved, USB-C Monitor", "2499.00"};
        // embedded double quotes
        String[] record2 = {"Dell", "", "Alienware 38 Curved \"Gaming Monitor\"", "6699.00"};
        // embedded double quotes and commas
        String[] record3 = {"Samsung", "", "49\" Dual QHD, QLED, HDR1000", "6199.00"};
        // embedded line break
        String[] record4 = {"Samsung", "", "Promotion! Special Price\n49\" Dual QHD, QLED, HDR1000", "4999.00"};

        List<String[]> list = new ArrayList<>();
        list.add(header);
        list.add(record1);
        list.add(record2);
        list.add(record3);
        list.add(record4);

        return list;

    }

}

Review the CSV file content. All the embedded commas, double quotes, and line breaks are enclosed in double-quotes.

c:\\test\\monitor.csv

"Make","Model","Description","Price"
"Dell","P3421W","Dell 34, Curved, USB-C Monitor","2499.00"
"Dell","","Alienware 38 Curved ""Gaming Monitor""","6699.00"
"Samsung","","49"" Dual QHD, QLED, HDR1000","6199.00"
"Samsung","","Promotion! Special Price
49"" Dual QHD, QLED, HDR1000","4999.00"

2. Single class CSV writer – Write data to a CSV file

2.1 The OpenCSV library is good, but it contains many dependencies, which let me wonder if we really need a third party library to write data to a CSV file, it’s up to your preference.

2.2 However, below is my single class CSV writer implementation. It supports a custom separator and takes care of the embedded commas, double quotes, and line breaks. Read code comments for self-explanatory. The key is in the method formatCsvField(final String field, final boolean quote), which defines how to format the CSV fields.

CsvWriterSimple.java

package com.mkyong.io.csv;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CsvWriterSimple {

    private static final String COMMA = ",";
    private static final String DEFAULT_SEPARATOR = COMMA;
    private static final String DOUBLE_QUOTES = "\"";
    private static final String EMBEDDED_DOUBLE_QUOTES = "\"\"";
    private static final String NEW_LINE_UNIX = "\n";
    private static final String NEW_LINE_WINDOWS = "\r\n";

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

        CsvWriterSimple writer = new CsvWriterSimple();
        writer.writeToCsvFile(createCsvDataSpecial(), new File("c:\\test\\monitor.csv"));

    }

    public String convertToCsvFormat(final String[] line) {
        return convertToCsvFormat(line, DEFAULT_SEPARATOR);
    }

    public String convertToCsvFormat(final String[] line, final String separator) {
        return convertToCsvFormat(line, separator, true);
    }

    // if quote = true, all fields are enclosed in double quotes
    public String convertToCsvFormat(
            final String[] line,
            final String separator,
            final boolean quote) {

        return Stream.of(line)                              // convert String[] to stream
                .map(l -> formatCsvField(l, quote))         // format CSV field
                .collect(Collectors.joining(separator));    // join with a separator

    }

    // put your extra login here
    private String formatCsvField(final String field, final boolean quote) {

        String result = field;

        if (result.contains(COMMA)
                || result.contains(DOUBLE_QUOTES)
                || result.contains(NEW_LINE_UNIX)
                || result.contains(NEW_LINE_WINDOWS)) {

            // if field contains double quotes, replace it with two double quotes \"\"
            result = result.replace(DOUBLE_QUOTES, EMBEDDED_DOUBLE_QUOTES);

            // must wrap by or enclosed with double quotes
            result = DOUBLE_QUOTES + result + DOUBLE_QUOTES;

        } else {
            // should all fields enclosed in double quotes
            if (quote) {
                result = DOUBLE_QUOTES + result + DOUBLE_QUOTES;
            }
        }

        return result;

    }

    // a standard FileWriter, CSV is a normal text file
    private void writeToCsvFile(List<String[]> list, File file) throws IOException {

        List<String> collect = list.stream()
                .map(this::convertToCsvFormat)
                .collect(Collectors.toList());

        // CSV is a normal text file, need a writer
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
            for (String line : collect) {
                bw.write(line);
                bw.newLine();
            }
        }

    }

    private static List<String[]> createCsvDataSpecial() {

        String[] header = {"Make", "Model", "Description", "Price"};
        String[] record1 = {"Dell", "P3421W", "Dell 34, Curved, USB-C Monitor", "2499.00"};
        String[] record2 = {"Dell", "", "Alienware 38 Curved \"Gaming Monitor\"", "6699.00"};
        String[] record3 = {"Samsung", "", "49\" Dual QHD, QLED, HDR1000", "6199.00"};
        String[] record4 = {"Samsung", "", "Promotion! Special Price\n49\" Dual QHD, QLED, HDR1000", "4999.00"};

        List<String[]> list = new ArrayList<>();
        list.add(header);
        list.add(record1);
        list.add(record2);
        list.add(record3);
        list.add(record4);

        return list;

    }

}

Review the CSV file content. The embedded commas, double quotes, and line breaks are enclosed with double quotes properly. The output is the same as the above OpenCSV 1.4 example.

c:\\test\\monitor.csv

"Make","Model","Description","Price"
"Dell","P3421W","Dell 34, Curved, USB-C Monitor","2499.00"
"Dell","","Alienware 38 Curved ""Gaming Monitor""","6699.00"
"Samsung","","49"" Dual QHD, QLED, HDR1000","6199.00"
"Samsung","","Promotion! Special Price
49"" Dual QHD, QLED, HDR1000","4999.00"

3. Single class CSV writer – Unit Tests

Here are some unit tests for the the above CsvWriterSimple.

CsvWriterSimpleTest.java

package com.mkyong.io.csv;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CsvWriterSimpleTest {

    private CsvWriterSimple writer = new CsvWriterSimple();

    @Test
    void test_convert_csv_line_default() {
        String[] record = {"1", "apple", "10", "9.99"};
        String expected = "\"1\",\"apple\",\"10\",\"9.99\"";

        String result = writer.convertToCsvFormat(record);
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_empty() {
        String[] record = {"1", "", "10", ""};
        String expected = "\"1\",\"\",\"10\",\"\"";

        String result = writer.convertToCsvFormat(record);
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_custom_separator() {
        String[] record = {"1", "apple", "10", "9.99"};
        String expected = "\"1\";\"apple\";\"10\";\"9.99\"";

        String result = writer.convertToCsvFormat(record, ";");
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_no_quoted() {
        String[] record = {"1", "apple", "10", "9.99"};
        String expected = "1,apple,10,9.99";

        String result = writer.convertToCsvFormat(record, ",", false);
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_contains_comma() {
        String[] record = {"1", "apple,orange", "10", "9.99"};
        String expected = "\"1\",\"apple,orange\",\"10\",\"9.99\"";

        String result = writer.convertToCsvFormat(record);
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_contains_double_quotes() {
        String[] record = {"1", "12\"apple", "10", "9.99"};
        String expected = "\"1\",\"12\"\"apple\",\"10\",\"9.99\"";

        String result = writer.convertToCsvFormat(record);
        assertEquals(expected, result);
    }

    @Test
    void test_convert_csv_line_contains_newline() {
        String[] record = {"1", "promotion!\napple", "10", "9.99"};
        String expected = "\"1\",\"promotion!\napple\",\"10\",\"9.99\"";

        String result = writer.convertToCsvFormat(record);
        assertEquals(expected, result);
    }

}

single class CSV writer unit tests

P.S Let me know if you found bugs in the CsvWriterSimple.

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-io/csv

References

About Author

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

Comments

Subscribe
Notify of
7 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Elijah
6 years ago

The above seems like a fine solution for small data sets, but what would be a better way to approach writing out MILLIONS of lines of data?
I feel the above would result in Out of Memory exceptions if trying to load into any list or objects.

Ashif
1 year ago

CsvWriterSimple will throw null point exception whenever there is null value for attributes..

Rey Floriene
2 years ago

Can you save the output on another folder like on the current user Downloads folder? Tried saving it like this “C:\\Users\\%username%\\Downloads\\test.csv” but encountered FileNotFound exception.

chandrakant
2 years ago

Hi mkyong,

i am facing some issue in unicode characters like “પ્રિય ગાહકો , રક્ષાબંધન પર્વ ની શુભકામનાઓ લી . સોફ્ટ ટેક સોલ્યૂશન , અમદાવાદ” it is not export properly . Please help.

Prateek
14 years ago

How can we embed an image in the CSV file??? Please help