Class Csv

java.lang.Object
com.google.common.labs.csv.Csv

public final class Csv extends Object
An easy-to-use CSV parser with lazy parsing support and friendly error reporting.

For example:


 import static com.google.common.labs.csv.Csv.CSV;

 // skip(1) to skip the header row.
 List<List<String>> rows = CSV.parseToLists(input).skip(1).toList();
 

Empty rows are ignored.

You can also use the header row, and parse each row to a Map keyed by the header field names:


 import static com.google.common.labs.csv.Csv.CSV;

 List<Map<String, String>> rows = CSV.parseToMaps(input).toList();
 

Starting from v9.5, spaces and tabs around double quoted fields are leniently ignored.

Also starting from v9.5, to write to CSV format, use the join(Collection) method to join to CSV format:


 import static com.google.common.labs.csv.Csv.CSV;

 String csv = CSV.join(myList);
 
Field values with newline, quote or comma will be automatically quoted, with literal double quote characters escaped.

You can also use the joining() collector:


 import static com.google.common.labs.csv.Csv.CSV;

 String csv = Stream.of("a", "b", "c").collect(CSV.joining());
 

Note that streams returned by this class are sequential and are not safe to be used as parallel streams.

  • Field Details

  • Method Details

    • withDelimiter

      public Csv withDelimiter(char delimiter)
      Returns an otherwise equivalent CSV parser but using delimiter instead of comma.
    • withComments

      public Csv withComments()
      Returns an otherwise equivalent CSV parser but allows comment rows.

      Comments are recognized by the presence of a hash sign (#) at the beginning of a line.

      Note that comments are not standard CSV specification.

    • parseToLists

      public Stream<List<String>> parseToLists(String csv)
      Parses the input string into a lazy stream of immutable List, one row at a time.

      No special treatment of the header row. If you know you have a header row, consider calling .skip(1) to skip it, or use parseToMaps(java.lang.String) with the field names as the Map keys.

    • parseToLists

      public Stream<List<String>> parseToLists(Reader csv)
      Parses the input reader into a lazy stream of immutable List, one row at a time.

      No special treatment of the header row. If you know you have a header row, consider calling .skip(1) to skip it, or use parseToMaps(java.lang.String) with the field names as the Map keys.

      Implementation note: the parser uses internal buffer so you don't need to wrap it in BufferedReader.

    • parseToMaps

      public Stream<Map<String,String>> parseToMaps(String csv)
      Parses csv string lazily, returning each row in a Map keyed by the field names in the header row. The first non-empty row is expected to be the header row.

      Upon duplicate header names, the latter wins. If you need alternative strategies, such as to reject duplicate header names, or to use ListMultimap to keep track of all duplicate header values, consider using parseWithHeaderFields(String, BiCollector) instead. That is:

      
       import static com.google.mu.util.stream.BiCollectors.toMap;
      
       CSV.parse(input, toMap());  // throw upon duplicate header names
       
      or:
      
       import static com.google.common.collect.ImmutableListMultimap;
      
       // keep track of duplicate header names
       CSV.parse(input, ImmutableListMultimap::toImmutableListMultimap);
       
    • parseToMaps

      public Stream<Map<String,String>> parseToMaps(Reader csv)
      Similar to parseToMaps(String), but takes a Reader instead.

      Implementation note: the parser uses internal buffer so you don't need to wrap it in BufferedReader.

    • parseWithHeaderFields

      public <R> Stream<R> parseWithHeaderFields(String csv, BiCollector<? super String, ? super String, ? extends R> rowCollector)
      CSV.parseWithHeaderFields(input, toMap()) will parse the non-header rows in the input string into a lazy stream of Map, keyed by the header field names.

      Usually, if you need a Map of field names to column values, consider using parseToMaps(String) instead. But if you need alternative strategies, such as collecting each row to a ListMultimap to more gracefully handle duplicate header names, you can use:

      
       import static com.google.common.collect.ImmutableListMultimap;
      
       CSV.parseWithHeaderFields(input, ImmutableListMultimap::toImmutableListMultimap);
       
    • parseWithHeaderFields

      public <R> Stream<R> parseWithHeaderFields(Reader csv, BiCollector<? super String, ? super String, ? extends R> rowCollector)
      CSV.parseWithHeaderFields(input, toMap()) will parse the non-header rows from the input reader into a lazy stream of Map, keyed by the header field names.
      
       import static com.google.common.collect.ImmutableListMultimap;
      
       CSV.parseWithHeaderFields(input, ImmutableListMultimap::toImmutableListMultimap);
       

      Implementation note: the parser uses internal buffer so you don't need to wrap it in BufferedReader.

    • join

      public String join(Collection<?> fields)
      Joins fields as a CSV row. If a field value is null, an empty string is used.
      Since:
      9.5
    • join

      public String join(Object... fields)
      Joins fields as a CSV row. If a field value is null, an empty string is used.
      Since:
      9.5
    • joining

      public Collector<Object,?,String> joining()
      Returns a collector that joins the input elements into a CSV row.

      If a field value is null, an empty string is used.

      Since:
      9.5
    • toString

      public String toString()
      Overrides:
      toString in class Object