Skip to content

Skipping lines before the CSV data

Some CSV files contain one or more lines of text before the actual CSV data starts. For example, it could look like this:

example.csv
This is an example of a CSV file that contains
three lines before the actual CSV records.
header 1,header 2
value 1,value 2

Strictly speaking, such a file is not a valid CSV file as defined by the CSV specification (RFC 4180).

The main problem with those files is:

  • When working with named fields, the very first line (This is an example of a CSV file that contains) would be interpreted as the actual header line.
  • An exception would be thrown with the default extraFieldStrategy(FieldMismatchStrategy.STRICT), as some lines have more fields than the first line.

FastCSV comes with two features to handle such files:

  • skipLines(int lineCount): Skip a specific number of lines (lineCount) regardless of their content.
  • skipLines(Predicate<String> predicate, int maxLines): Skip lines until a specific line (e.g., the header) is found. Throws a CsvParseException if none of the first maxLines lines matches.

This example demonstrates how to skip non-CSV head lines when reading such a CSV file with FastCSV.

ExampleCsvReaderWithNonCsvAtStart.java
import java.io.IOException;
import java.util.function.Predicate;
import de.siegmar.fastcsv.reader.CsvReader;
/// Example for reading CSV data with non-CSV data before the actual CSV header.
///
/// FastCSV supports Java 17 and later, but this code uses Java 25
/// for brevity, leveraging newer language features.
void main() throws IOException {
final String data = """
Your CSV file contains some non-CSV data before the actual CSV header?
And you don't want to (mis)interpret them as CSV header? No problem!
header1,header2
foo,bar
""";
alternative1(data);
alternative2(data);
}
void alternative1(final String data) throws IOException {
IO.println("Alternative 1 - ignore specific number of lines");
try (var csv = CsvReader.builder().ofNamedCsvRecord(data)) {
// Skip the first 3 lines
IO.println("Skipping the first 3 lines");
csv.skipLines(3);
// Read the CSV data
csv.forEach(IO::println);
}
}
void alternative2(final String data) throws IOException {
IO.println("Alternative 2 - wait for a specific line");
final Predicate<String> isHeader = line ->
line.contains("header1");
try (var csv = CsvReader.builder().ofNamedCsvRecord(data)) {
// Skip until the header line is found, but not more than 10 lines
final int actualSkipped = csv.skipLines(isHeader, 10);
IO.println("Found header line after skipping " + actualSkipped + " lines");
// Read the CSV data
csv.forEach(IO::println);
}
}

You also find this source code example in the FastCSV GitHub repository.