0

I am currently learning Java and received the following task, that I cannot seem to solve:

"Create a Java program that prints one random poem of 5 lines in the console. The poems must be read from a text file."

I have copied 10 different poems inside a text file, all written underneath each other. I managed to make the program print out the very first poem (first 5 lines) in the console, but first of all, I am not sure if it's the correct way to do such, and I don't know how to make the program print out one random poem (5 lines that belong together) each time I run it.

Here is the farthest I could get:

public static void main(String[] args) throws IOException {
    File file = new File("src/main/java/org/example/text.txt");

    Scanner scanner = null;
    try {
        scanner = new Scanner(file);

        int i = 0;
        while (scanner.hasNext()) {
            String line = scanner.nextLine();
            if (i < 5) {

                i++;
                System.out.println(line);
            }
        }
    } catch (Exception e) {

    }
}
Chaosfire
  • 4,818
  • 4
  • 8
  • 23
Kev98
  • 1
  • 2
  • 2
    Is it required to store 10 poems in a single file? How are the poems delimited? I mean what marks the end of one poem? A blank line or something like that? – ashish.g Nov 23 '22 at 16:28
  • In fact it is required to use all 5-line poems (limericks) of a specific website and somehow have them all in one text file. I‘m not sure how to have all of them, so I decided to test it out with 10 poems at least. Currently the poems are not separated by any blank lines or anything because I thought it would bring more problems. All lines are listed underneath each other bluntly, but I could change that if it‘s inefficient. – Kev98 Nov 23 '22 at 16:36
  • 1
    If all the poems will definitely be of five lines, you can generate a random number, multiply it by 5, that will be the start of your random poem and you can continue reading next five lines. – ashish.g Nov 23 '22 at 16:42
  • Wouldn’t the problem occur that the program prints two lines from one poem and three from the following for example? Wouldn’t the poems get mixed up? And yes, they always consist of five lines. Could you possibly show me your solution through code? I am very new and unsure how to implement this. – Kev98 Nov 23 '22 at 16:48
  • If every poem is of 5 lines, 1st, 6th , 11th line (or 0th, 5th, 10th line, when following 0 based indexing) and so on would be the first line of 1st, 2nd, 3rd poems. There would not be a mix up. You need to generate the number 1,6,11....(or 0,5,10) etc. I would encourage you to write the code and paste edited code in the post. @Reto Höhener IMO The exercise is for reading a file. Also, reading the file into memory doesn't make much sense. – ashish.g Nov 23 '22 at 16:53

2 Answers2

0

You can try

private static final int POEM_LINES_LENGTH = 5;

public static void main(String[] args) throws IOException
{
    // The file
    File file = new File("src/main/java/org/example/text.txt");
    
    // Get all the lines into a single list
    List<String> lines = Files.readAllLines(Paths.get(file.getAbsolutePath()));
    
    // Get a random poem and point at the end.
    int poemFinish = new Random().nextInt(lines.size() / POEM_LINES_LENGTH) * POEM_LINES_LENGTH;
    
    // Point to the be start
    int start = poemFinish - POEM_LINES_LENGTH;
    
    // Create a sublist with the start and finish indexes.
    for (String line : lines.subList(start, poemFinish))
        System.out.println(line);
}
Melron
  • 569
  • 4
  • 10
  • The only problem i see is this solution is suitable for reading small files only as it reads entire file into memory. Also, start can sometimes be negative. – ashish.g Nov 23 '22 at 17:29
  • @ashish.g if you know the size of your poems, then you can change it. My logic there was about dynamic size. How the start point can be negative? – Melron Nov 23 '22 at 18:50
0

This will not read the entire file into the memory, hence large files can also be read.

  final int totalPoems = 17;
  int skip = new Random().nextInt(totalPoems) * 5;

  Path path = Paths.get("file.txt");
  BufferedReader reader = Files.newBufferedReader(path);
    
  while(skip-->0){
     reader.readLine();
  }
  
  for(int i=0; i<5; i++){
      System.out.println(reader.readLine());
  }

The downside is you have to know how many poems are in the file beforehand. If you don't want to do this you can quickly count the total number of lines/poems only one time.

ashish.g
  • 525
  • 11
  • 25