How To Read Text File With BufferedReader In Java

  • Post last modified:July 16, 2022
  • Reading time:4 mins read

Introduction

BufferedReader class is one of the most used when it comes to read Text files in Java.This class provides methods which can read characters from input stream. As name says it buffers read character hence efficient in reading files. In this article we will read csv file from Kaggle about Netflix top 10 movie using BufferedReader class .

Input File

I am using Netflix daily top 10 dataset from kaggle as my input file.

BufferedReader

BufferedReader class is provided by Java SDK and we don’t need any additional library. It provides enough methods to read CSV files from local disk.

Infrastructure code to get BufferedReader Object from CSV file on Disk looks like below

    // Get Buffered Reader object to Our Input CSV File
    private static BufferedReader getBufferedReader() throws FileNotFoundException {
        File file = new File(INPUT_CSV_FILE);
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        return bufferedReader;
    }

File Reading Logic

  • BufferedReader class provides method readLine() to read each line from CSV file.
    readLine() Reads a line of text & line is considered to be terminated by any one of a line feed (‘\n’), a carriage return (‘\r’), or a carriage return followed immediately by a linefeed.
  • Each line would be String and we can split that string using comma delimiter for CSV. If its tab we can use tab separator as well.
  • Once we have String array of CSV fields then its good practice to convert that into Java POJO using mapper class. In our case , we have created MovieMapper class that has logic to map CSV fields to Java object.
private static List<NetflixTop10Movies> CSVReadWithBufferedReader(List<String> errorRecord, List<NetflixTop10Movies> top10NetflixMoviesList, MovieMapper movieMapper) throws IOException {
        BufferedReader bufferedReader = getBufferedReader();
        String readLine = null;
        int lineNumber = 1;
        while ((readLine = bufferedReader.readLine())!=null) {
            if (!isfirstLine(lineNumber)) { // skip header
                String[] csvFields = readLine.split(CSV_DELIMETER);
                // map to POJO
                Movie movie = movieMapper.mapToMovies(csvFields);
                if (movie == null) {
                    errorRecord.add(readLine); // i decided to add to error record list , maybe we can write to errorfile eventually.
                    continue;
                }
                NetflixTop10Movies netflixTop10Movies = movieMapper.mapToNetflixTop10Movies(csvFields, movie);
                top10NetflixMoviesList.add(netflixTop10Movies);
            }
            lineNumber++;
        }
        return top10NetflixMoviesList;
    }

Output

We decided to just console print the validated record , but in real word scenario you would either perform certain transformation or just insert into some sink such as database .

Client code

  • Our client code create two list, one for error record and other for valid records. If we encounter error records we should filter it out from our input records and write to separate sink maybe some sort of error file which operation team member can look into later.
  • For validated records we can further process maybe do some grouping operation or some sort of further transformation based on business logic and finally write it down to some Sink. Here i have just output on console.
    public static void main(String[] args) throws IOException {
        // list to capture error in csv records
        List<String> errorRecord = new ArrayList<>();
        // list to capture validated records
        List<NetflixTop10Movies> top10NetflixMoviesList = new ArrayList<>();
        // Mapper class to map objects
        MovieMapper movieMapper = new MovieMapper();
        // Buffered Reader Class to read CSV File
        List<NetflixTop10Movies> netflixTop10Movies = CSVReadWithBufferedReader(errorRecord, top10NetflixMoviesList, movieMapper);

        top10NetflixMoviesList.stream().forEach(listedMovie ->{
            System.out.println("As of(date) , Title : "+listedMovie.getAsOf()+", "+listedMovie.getMovie().getTitle());
        });
    }

List of other methods

Read using lines() method
This method returns Stream<String>, suitable for reading csv reacord as stream of record and use functional style programming

Stream<Movie> movieStream = bufferedReader.lines()
                .map(eachLine -> eachLine.split(CSV_DELIMETER))
                .map(eachRecord -> movieMapper.mapToMovies(eachRecord));

Read using read() method

This method read file character by character. Since the return value is int we need to parse it to char.

int num =0;
char readChar;
 while((num = bufferedReader.read())!=-1){
            readChar = (char) num;
            System.out.println("readChar : "+readChar);
}

Read using read(cbuff,off,len) method
Read characters into a portion of an array. In below example read character will be stored in readChar char[] array which will start reading from offset and will read until defined length.

int num = bufferedReader.read(readChar,offSet,length)
System.out.println("readChar : "+new String(readChar,0,num))

Conclusion

Java BufferedReader class provides methods to read text file which is sufficient for many use cases. It provides Stream of Input source as well which can be useful for folks who love functional programming.It is thread safe as well that means if more than one thread try to access Bufferedreader object it will put lock using synchronized and avoid inconsistent result.

Further Readings

Leave a Reply