3

I am making a Class called Book that represents books that have a title, an author and a year, when they won the award.

I have a method getList which should read in the data from a csv file and if a line doesn’t follow the pattern title,author,year then a message should be written to the standard error stream. I am having trouble determine how to specify the error message.

I can read in the file using BufferedReader

However, when it comes verifying all 3 values are there (title, author, year) I am not sure where to start. I imagine I need 3 variables which would check if (year, author, etc) is missing in one of the lines of the csv. I'm new to buffered reader and not sure how to go about this. any help is appreciated

I have looked on the internet and haven't found exactly what I'm looking for

  package books;

 import java.io.BufferedReader;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.List;

 public class Book implements Comparable<Book> {
private String title;
private String author;
private int year;

/**
 * @param title
 * @param author
 * @param year
 */
public Book(String title, String author, int year) {
    this.title = title;
    this.author = author;
    this.year = year;
}

public String getTitle() {
    return title;
}

public String getAuthor() {
    return author;
}

public int getYear() {
    return year;
}

@Override
public String toString() {
    return title + " by " + author + " (" + year + ")";

}

public static List<Book> getList(String file) {

    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
        while (reader.ready()) {

            System.out.println(reader.readLine());
        }
        System.out.println();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

@Override
public int compareTo(Book o) {
    // TODO Auto-generated method stub
    return 0;
}

  }

tests app

 package books;


 public class BookApp {

public static void main(String[] args)  {
    Book book = new Book ("Harry Potter and the Sorcerer's Stone", "J. K. Rowling", 1997);
    System.out.println(book.toString());

    System.out.println();
    book.getList("src/books/books.csv");
}
}

1 Answers1

1

Heey you can use the following code to parse and validate the books:


public static List<Book> getList(String file) {
// create a new list of books
    List<Book> books = new ArrayList<>();
    try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
        while (reader.ready()) {
            // read line of reader
            String bookLine = reader.readLine();
            Book book = toBook(bookLine);
            if (book != null) { //only add the book if it is non empty
                books.add(book);
            }
        }
        System.out.println();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return books;
}

private static Book toBook(String bookLine) {
    String[] bookParts = bookLine.split(",");
    if (bookParts.length < 3) { //validate if all three parts are present
        System.err.println(String.format("The line %s did not contain all parts", bookLine));
        return null;
    }
    if (bookParts[0].trim().isEmpty()) { // validate the book has a title
        System.err.println(String.format("The line %s did contain an empty title", bookLine));
        return null;
    }

    if (bookParts[1].trim().isEmpty()) { // validate the book has an author
        System.err.println(String.format("The line %s did contain an empty author", bookLine));
        return null;
    }
    if (!bookParts[2].trim().matches("\\d{4}")) { // checks if the year (3rd part is a number. Where \\d is for numeric and {4} means 4 digits)
        System.err.println(String.format("The line %s did contain a non-numeric value as year", bookLine));
        return null;
    }
    return new Book(bookParts[0], bookParts[1], Integer.parseInt(bookParts[2]));
}

Stephan Hogenboom
  • 1,543
  • 2
  • 17
  • 29
  • I did some testing and noticed that if you enter a string instead of a an int for the year, I get an NumberFormatException error instead of the message: "The line %s did not contain a numeric value as year". Do you have any suggestions? I could do a catch (NumberFormatException e) but I'm not able to pull in the line data from the method Book toBook – user9676458363 Aug 26 '19 at 16:44
  • Ill look into it later :) what was your input? – Stephan Hogenboom Aug 26 '19 at 16:58
  • I have this line in the csv: The Brief, Wondrous Life of Oscar Wao,Junot Diaz. – user9676458363 Aug 26 '19 at 18:02
  • I also noticed if I add a counter to count how many books are in the csv file it only shows half of them. For example: I have 16 books but only shows 8. I am incrementing the book counter variable in the while loop. Any suggestions? – user9676458363 Aug 26 '19 at 18:05
  • @user9676458363 I did some testing and i did get the "The line %s did not contain a numeric value as year" log line. Do you have the exclamation mark (`!`) before the check in `(!bookParts[2].trim().matches("\\d{4}"))`? I can help you with the counter but i think it would be better if you open another question with your current counter code ;). I think you should increment the counter in the null check or the toBook method – Stephan Hogenboom Aug 26 '19 at 20:34