Java read CSV example with custom parsing

In this example we will be using Bitcoin data in CSV (comma-separated values file) which we will custom parse and load in our application. Then user have to provide date in format year-month-day (yyyy-MM-dd) and the program will print the highest BTC (Bitcoin) price and the lowest BTC (Bitcoin) price in United States dollars.

In this program there are a lot of actions so lets unfold them. First you need to have data. I download mine from https://finance.yahoo.com/quote/BTC-USD/history/ where I get the history of the Bitcoin for the last year in CSV format.

I also will attach my file in case you just want to download it:

CSV file is a comma-separated values file but if we open it with tool like Microsoft Excel or LibreOffice Calc we will see that the file is recognized and separated by rows and columns. In this case first row is header row and contain the names of the column:

DateOpenHighLowCloseAdj CloseVolume
2021-10-3161850.48828162406.17187560074.32812561318.95703161318.95703132241199927
2021-11-0161320.44921962419.00390659695.18359461004.4062561004.4062536150572843
2021-11-0260963.25390664242.79296960673.05468863226.40234463226.40234437746665647
2021-11-0363254.33593863516.937561184.23828162970.04687562970.04687536124731509
2021-11-0462941.80468863123.28906360799.66406361452.23046961452.23046932615846901
2021-11-0561460.07812562541.4687560844.60937561125.67578161125.67578130605102446
2021-11-0661068.87561590.68359460163.7812561527.48046961527.48046929094934221
Bitcoin data rows inside BTC-USD.csv file

So now lets see see how the program is working:

  • Let’s look closer into method parseStringToDataRow. Inside the line (which is string) will be split by “,” into array of string and then knowing the index of the columns we can get each data separately.
  • From all of the column only first column “Date”, third column “High” and forth column “Low” (look at the document structure above) are interesting for us. So from this strings we create LocalDate (with format yyyy-MM-dd ), BigDecimal and BigDecimal (Rounding BigDecimal values with 2 Decimal Places)
  • Normally data is sorted in this file but just to be sure lets sorting it by date
  • The program find and it will show to the user which is the earliest and latest date
  • After the data is ready the program will ask the user to give a date in a same format yyyy-MM-dd
  • The program will check if user input date is between the first date in the file and the last date
  • In the end we are filtering for this date with Predicate.
  • If we find the record we display the Bitcoin highest and lowest price for that day.
  • If there is missing data which we require then error message will print: No data was found in the file for this date!
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;

public class MainReadCSV {
    private record DataRow(LocalDate date, BigDecimal high, BigDecimal low) {
    }

    private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public static void main(String[] args) {
        // Use 'try' to close Scanner and release taken resources.
        // Connect the scanner to System.in (keyboard)
        try (Scanner in = new Scanner(System.in)) {
            String initMsg = """
                    Please enter the path to the file and please
                    don't leave empty spaces else they need to be escaped.
                    1. If you are using Windows then make
                        sure you path looks in format:
                        c:\\folder\\BTC-USD.csv
                    2. If you are using Linux/Unix then the format:
                        /home/username/BTC-USD.csv
                    fileInput:
                    """;
            System.out.print(initMsg);

            String filePathString = in.nextLine();
            // check if the file exist:

            Path path = Paths.get(filePathString);
            if (Files.notExists(path)) {
                System.err.println("File path is incorrect!! Please double check the value!");
                return;
            }

            List<DataRow> data = readFile(path);

            List<DataRow> sortedData = data.stream()
                    .sorted(Comparator.comparing(DataRow::date))
                    .toList();

            String msg = """
                    File found. Please write date for which you want to see the data.
                    The date format must be like 2021-11-01 -> year-month-day.
                    Please consider that date range is from %s until %s date.
                    Date input:
                    """;

            LocalDate startDate = sortedData.get(0).date;
            LocalDate endDate = sortedData.get(sortedData.size() - 1).date;

            System.out.format(msg, startDate.format(dtf), endDate.format(dtf));
            String dateForSearching = in.nextLine();
            LocalDate localDateUserInput = LocalDate.parse(dateForSearching, dtf);

            if(startDate.isAfter(localDateUserInput))
            {
                System.err.print("User input date is before first date inside file!!");
                return;
            }

            if(endDate.isBefore(localDateUserInput))
            {
                System.err.print("User input date is after last date inside file!!");
                return;
            }

            Optional<DataRow> result = sortedData.stream()
                    .filter(d -> d.date.equals(localDateUserInput))
                    .findFirst();

            String outputString = "Bitcoin price for this day high -> %s , low -> %s";
            result.ifPresentOrElse(
                    dataRow -> System.out.format(outputString, dataRow.high, dataRow.low),
                    () -> System.err.print("No data was found in the file for this date!")
            );
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static List<DataRow> readFile(Path path) throws IOException {
        List<DataRow> dataRows;
        try (BufferedReader reader = Files.newBufferedReader(path)) {
            dataRows = reader.lines()
                    .skip(1)
                    .map(MainReadCSV::parseStringToDataRow).toList();
        }
        return dataRows;
    }

    private static DataRow parseStringToDataRow(String line) {
        String[] parts = line.split(",");
        LocalDate date = LocalDate.parse(parts[0], dtf);
        BigDecimal high = new BigDecimal(parts[2]);
        BigDecimal highRounded = high.setScale(2, RoundingMode.HALF_EVEN);
        BigDecimal low = new BigDecimal(parts[3]);
        BigDecimal lowRounded = low.setScale(2, RoundingMode.HALF_EVEN);
        return new DataRow(date, highRounded, lowRounded);
    }
}

Output:

Please enter the path to the file and please
don't leave empty spaces else they need to be escaped.
1. If you are using Windows then make
    sure you path looks in format:
    c:\folder\BTC-USD.csv
2. If you are using Linux/Unix then the format:
    /home/username/BTC-USD.csv
fileInput:
/home/user/Downloads/BTC-USD.csv
File found. Please write date for which you want to see the data.
The date format must be like 2021-11-01 -> year-month-day.
Please consider that date range is from 2021-10-31 until 2022-10-31 date.
Date input:
2021-12-01
Bitcoin price for this day high -> 59041.68 , low -> 56553.08

Leave a Comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.