This question already has answers here:
How do I generate random integers within a specific range in Java?
(72 answers)
Closed 3 months ago.
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) {
}
}
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);
}
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.
I want to put a newline character at a certain position instead of all of my numbers then newline character.
I tried to put the newline character with System.out.print("\n"); outside of the loop but I can't figure out how to put it at a certain position. I want my chart to be a simple 10 x 10 chart, with 10 numbers per row, 10 rows in total. My numbers.txt has 100 random numbers.
import java.io.*;
public class numbersChart {
public static void main(String[] args) throws IOException {
File myFile = new File("numbers.txt");
Scanner text = new Scanner(myFile);
while (text.hasNextInt()) {
System.out.print("\n");
System.out.printf("%6s", " ");
System.out.print(text.nextInt());
}
}
}
You don't really need the while loop, the idea is to put \n after 10ths numbers.
Try the code below:
public static void main(String[] args) throws IOException {
File myFile = new File("numbers.txt");
Scanner scanner = new Scanner(myFile);
int d = 10;
for (int i = 0; i < d * d; i++) {
if (scanner.hasNextInt()) {
System.out.print(scanner.nextInt());
} else {
break;
}
if ((i + 1) % d == 0) {
System.out.println();
} else {
System.out.print(" ");
}
}
}
Build your rows as you read the file pretty much in the same fashion as you are doing. Print each row (of whatever) as they are developed. Using a while loop to read the file is the usual practice for this sort of thing since you may not necessarily know exactly how many numbers may actually be contained within the file to generate the chart (table). In your particular case you for whatever reason know there are going to be 100 numbers. This however may not always be the case in other real world situations. Your code should be able to create table rows of ten (or whatever you desire) whether there is 1 number or 1 million (or even more) numbers in the file.
A slightly different play on the task would be to consider a numerical data file which contains any number of numerical values be it signed or unsigned integer, floating point or both. We want to read this file so to create and display a numerical table consisting of whatever desired number of rows with all rows consisting of whatever number of columns with the exception of perhaps the last row which there may not be enough values in the data file to accommodate the require number of columns. The columns are to also be spaced to our desired width when creating the table.
With the supplied code below, this can all be accomplished. Maximum Rows, columns, and table spacing is all configurable. I suggest you read the comments in code for further insight:
/* Create a numbers.txt file for testing. Save a copy
of your existing one somewhere else for safekeeping
if you use this portion of code! */
int quantityOfNumbers = 100;
// 'Try With Resources' used here to auto-close the writer.
try (java.io.PrintWriter writer = new java.io.PrintWriter(new java.io.File("numbers.txt"))) {
for (int i = 1; i <= quantityOfNumbers; i++) {
writer.append(String.valueOf(i));
if (i < quantityOfNumbers) {
writer.write(System.lineSeparator());
}
}
writer.flush();
}
catch (FileNotFoundException ex) {
System.err.println(ex.getMessage());
System.exit(0);
}
// ---------------------------------------------------------------------
String fileName = "numbers.txt"; // The numerical data file to read.
int desiredColumns = 10; // The number of columns per row you want.
int formatSpacing = 8; // Each column will be this many spaces wide.
int maxRows = 0; // Max rows we might want. If 0 then unlimited.
java.io.File myFile = new java.io.File(fileName); // File Object
// Read & process the numerical data file...
// 'Try With Resources' used here to auto-close the reader.
try (Scanner reader = new Scanner(myFile)) {
String num;
StringBuilder sb = new StringBuilder(""); // Used for building each numerical row
int columnCounter = 0; // Used to keep track of columns added to 'sb'.
int rowCounter = 0; // Used to keep track of the number of rows created.
while (reader.hasNextLine()) { // Read file until there is nothing left to read.
num = reader.nextLine().trim(); // Retrieve data line on each iteration.
/* Make sure the line in the file is actually a number
and not something alphanumeric or a blank line. Carry
out some form of validation. The regular expression
(regex) within the matches() method allows for signed
or unsigned integer or floating point string numerical
values. If it's invalid we skip the line. Remove this
`if` block if you want everything regardless: */
if (!num.matches("-?\\d+(\\.\\d+)?")) {
continue;
}
columnCounter++; // Valid line so increment Column Counter by 1
/* Format the string value as we append to sb. If you want the
table values right justified then remove the '-' from the format. */
sb.append(String.format("%-" + String.valueOf(formatSpacing) + "s", num));
if (columnCounter == desiredColumns) { // Have we reached our desired number of columns?
System.out.println(sb.toString()); // Print the row to console.
sb.setLength(0); // Clear the StringBuilder object (sb).
columnCounter = 0; // Reset the Column Counter to 0.
rowCounter++; // Increment Row Counter by 1
if (rowCounter == maxRows) { // If we've reach our max rows then stop reading.
break; // Break out of 'while' loop.
}
}
}
/* Reading has finished but is there anything that didn't
make 10 columns worth of data? If the StringBuilder
object (sb) contains anything at this point then yes
there is something so print it to console window. */
if (!sb.toString().isEmpty()) {
System.out.println(sb.toString());
}
}
catch (FileNotFoundException ex) {
// Whoops...can't find the numerical data file.
System.err.println("Can not locate the numerical data file!");
System.err.println("Data File: --> " + myFile.getAbsolutePath());
}
public static Matrix read(String filename) {
Scanner scan = new Scanner(filename);
int row = scan.nextInt();
int column = scan.nextInt();
Matrix mat = new Matrix(row, column);
scan.nextLine();
for(int i=0; i<row; i++) {
for(int j=0; j<column; j++) {
mat.setElement(i, j, scan.nextInt());
}
scan.nextLine();
}
scan.close();
return mat;
}
This is currently my method to read a text file. Each text file has the matrix dimensions written at the top and then the rows of the matrix below. Ex:
2 3
1 1 1
2 2 2
When I try to store the first 2 numbers in the first row as the row and column indices, I get an input mismatch exception.
Probable cause of your issue
Whenever you take inputs from the user using a Scanner class. If the inputs passed doesn’t match the method or an InputMisMatchException is thrown. For example, if you reading an integer data using the nextInt() method and the value passed in a String then, an exception occurs.
Handling input mismatch exception
The only way to handle this exception is to make sure that you enter proper values while passing inputs. It is suggested to specify required values with complete details while reading data from user using scanner class.
Forgive me if this has already been asked, but I am trying to fill an array of user defined size, but I want to make sure any extra input is either dumped or triggers an error to reprompt for input. My assignment requires that all input for an array is done on one line, with spaces separating individual values. The program works fine, and seeing how we are still in the beginning of the class I don't think that we are expected to know how to filter the quantity of inputs on a single line, but it is something that still bugs me.
I have searched for some time now for a solution, but everything thing I find is not quite what I am looking for. I thought doing a while(scannerVariable != "\n") would work, but once I thought about it more I realized that wouldn't do anything for my problem since the new line character is only being encountered once per array regardless of the number of inputs. The snippet with the problem is below:
public static double[] getOperand(String prompt, int size)
{
System.out.print(prompt);
double array[];
array = new double[size];
for(int count = 0; count < size; count++)
{
array[count] = input.nextDouble();
}
return array;
}
All I need is some way of validating the number of inputs or dumping/ignoring extra input, so that there is no trash in the buffer to skip input that follows. The only way I can think of is counting the number of spaces and comparing that against the size of the array -1. I don't think that would be reliable though, and I'm not sure how to extract a whitespace character for the count unless I were to have all the input go into a string and parse it. I can post more code or provide more details if needed. As always, thanks for any help!
This can help you. Function that allows the entry of numbers on a line separated by spaces. Valid numbers are stored in a list of type Double.
public static void entersDouble () {
Scanner input = new Scanner(System.in);
String s;
ArrayList<Double> numbers= new ArrayList<>();
System.out.print("Please enter numbers: ");
s=input.nextLine();
String [] strnum = s.split("\\s+");
int j=0;
while(j<strnum.length){
try {
numbers.add(Double.parseDouble(strnum[j++]));
}
catch(Exception exception) {
}
}
for (Double n : numbers)
System.out.println(n);
}
It seems to me that rather than trying to work out the number of inputs up front you would be better off trying to read them one by one and then taking appropriate action if it's too long or too short.
For example
public static double[] getOperands(String prompt, int size) {
double[] operands = new operands[size];
while (true) {
System.out.println(prompt);
Scanner scanner = new Scanner(System.in);+
int operandCount = 0;
while (scanner.hasNextDouble()) {
double val = scanner.nextDouble();
if (operandCount < size)
operands[operandCount++] = val;
}
if (operandCount == size)
return operands;
else
System.out.println("Enter " + size + " decimals separated by spaces.");
}
}
I'm pretty new to programming and working on an assignment for class. Now, I'm not asking for anyone to write my code for me but I'm stuck with a runtime error. In the assignment we need to read a file, use the first line, "15", to initialize the size of an array, and proceed to fill the array with the information from each line.
edit: I didn't want to post all of the code because I thought it would look too long but because of the downvotes for being vague, here it goes.
File:
15
produce,3554,broccoli,5.99,1
produce,3554,broccoli,5.99,1
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
produce,3555,carrots,2.23,0.25
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2345,windex,5.99,1 unit
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2346,toilet paper,12.99,4 rolls
cleaning,2335,windex,2.25,1 mini sprayer
cleaning,1342,wipes,3.99,10 units
cleaning,1342,wipes,3.99,10 units
produce,3546,lettuce,2.99,0.5
My Error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15
at Inventory.readFile(Inventory.java:45)
at Inventory.<init>(Inventory.java:12)
at Supermarket.main(Supermarket.java:3)
Class with the Line 45 in Question (line 45 is commented, scroll to the right)"
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
public class Inventory{
Product[] list;
String[] invData;
private int i = 0;
public int count;
public Inventory (String f){
readFile(f);
}
public int indexOfProduct(int code){
for(i=0; i<list.length; i++){
if (list[i] != null)
if (list[i].getCode() == code)
return i;
}
return -1;
}
public Product delete(int pos){
Product temp = new Product();
temp = list[pos];
list[pos] = null;
return temp;
}
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine();
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]); // This is Line 45, Where the error occurs
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
public Product findCode(int c){
for(int i=0; i<list.length;i++)
if(list[1].getCode() == c)
return list[i];
return null;
}//end of method
}//end of class
Why did I get an "ArrayIndexOutOfBoundsException"? I hope someone can point out the flaw in my logic so I don't repeat it again.
Your issue is clearly with the use of i, as that is the only variable index on that line, and the out of range index is "15", which is just past the end of your 15-item array. So, couple of issues, all surrounding the use of i:
As nhellwig mentioned, be sure that i is actually initialized to 0 before calling this function.
Additionally, you're putting a lot of faith in the consistency of the item number in the file and the actual number of items. You should either produce a warning and stop trying to store items in the array if i >= itemCount, or use a container like an ArrayList that can grow to accommodate new items instead of a fixed size array.
Edit: Also, I should point out that you increment i whether you read an item or not, which means even blank lines will increment i, causing gaps in your list or array overruns. Since itemCount is the number if items, you should stick to that and only increment i if you read an actual item.
In that same spirit, you should verify that invData.length == 5 after you call split(), because a misplaced comma, etc. in your file may also end up with an OOB error. Granted, for your project, it's probably OK to make assumptions about the number of elements in a line that starts with "produce" or "cleaning", but in general it's important to be cautious with data coming from a user-created file.
I found the answer to be that I needed an "s.nextLine();"
Because I used "s.nextInt();" the pointer was just hangin around at the end of "15" in my file. Then, when the first line in the While loop "String line = s.nextLine();" executed the pointer moved from the end of 15 to before the p in produce in the 2nd line of the list file.
The working method looks like this:
public void readFile(String fileName){
try{
File invList = new File (fileName);
Scanner s = new Scanner(invList);
int itemCount = s.nextInt();
s.nextLine(); // This is the new line that made it work
list = new Product[itemCount];
count = itemCount;
while (s.hasNext()){
String line = s.nextLine(); //moves file pointer over one
invData = line.split(",");
if (invData[0].equals("produce")){
list[i] = new Produce(invData[1], invData[2], invData[3], invData[4]);
} else if(invData[0].equals("cleaning")){
list[i] = new Cleaning(invData[1], invData[2], invData[3], invData[4]);
}
i++;
}//end of while loop
} catch (FileNotFoundException Abra) {
String error = Abra.getMessage();
System.out.println(error);
}
} // end of method
How many times do you call readFile? You should have i = 0; at the beginning of the function.
"i" should not be a global value but should be a method local variable, initialized to zero.