Random line select from a file - java

I'm trying to make a method that a random line from lol.txt (which has 113 lines) would be chosen and sent out as message box. How it should work:
Generates random number from 0 till 112
a for loop should go over the random number of lines
output the randomly generated line as a message box
In my case step 2 doesn't work so I was hoping that someone could suggest on that. Here's the code:
public void close(){
try{
Random random = new Random();
int randomInt = random.nextInt(112);
FileReader fr = new FileReader("lol.txt");
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
Scanner scan = null;
for (int i = 0; i < randomInt + 1; i++) {
scan = new Scanner(line);
line = scan.nextLine();
}
JOptionPane.showMessageDialog(null,line);
}catch (IOException e){
JOptionPane.showMessageDialog(null,e.getMessage()+" for lol.txt","File Error",JOptionPane.ERROR_MESSAGE);
}
}
If you want to send me the solution with an array list that's fine but I would really like it to be how I planned it initially.

It's best to use a list for this purpose, as well as make the random size dynamic to adjust to the size of your file. In case you wanted to add more lines without having to change code.
BufferedReader reader = new BufferedReader(new FileReader("lol.txt"));
String line = reader.readLine();
List<String> lines = new ArrayList<String>();
while (line != null) {
lines.add(line);
line = reader.readLine();
}
Random r = new Random();
String randomLine = lines.get(r.nextInt(lines.size()));
JOptionPane.showMessageDialog(null,randomLine);

You only read the first line, and that's why you only get the first line. Try this..
String line = reader.readLine();
for (int i = 0; i < randomInt + 1; i++) {
line = reader.readLine();
}
What you are doing is reading a line from file, using that line to create a new Scanner with every iteration of loop and then read it back into line

Related

Java BufferedReader won't go to the next line

Sorry for the noob question, but I feel like my code is correct but I can't see why the read won't go to the next line:
This is my code so far:
BufferedReader buffer = null;
try {
FileReader file = new FileReader(filename);
buffer = new BufferedReader(file);
String line = buffer.readLine();
String[] separations = line.split(", ");
System.out.println(separations[0]);
while(line!= null) {
this.times.add(separations[0]);
Double number = Double.parseDouble(separations[1]);
allNumbers.add(number);
line = buffer.readLine();
}
The issue was not that the buffer was only reading one line but I was tokenizing the line outside of the loop, so the same information got stored for x number of lines:
Solution:
while (line != null) {
String[] separations = line.split(", "); // this should be inside the loop
if (separations.length > 1) {
this.times.add(separations[0]);
Double number = Double.parseDouble(separations[1]);
allNumbers.add(number);
}
line = buffer.readLine();
}

StringTokenizer NoSuchElements

I have created a method that reads a file set like this (//... are comments, ignore them):
5 // n jobs
2 // n tools
1 4 5 6 2
1 5 4 2 3
The matrix represents the tools used for each job but it doesn't really matter here.
Here is the method :
public static JobS inputJobMatrix(){
String line = ""; // Line in tokenizer
int jobN = inputJobN(); //First number of the file (jobs) works
int toolN = inputToolN(); //Second number of the file (tools) works
//Instancing JobS object
JobS inputJobS = new JobS(jobN, toolN);
int[][] tabFill = new int[jobN][toolN];
int[] tabFillOrder = new int[jobN];
try {
// Initializing reader.
FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr);
StringTokenizer st = new StringTokenizer(line);
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
//Instancing tab for Job Order 1...n
int[] a = new int[jobN];
for (int i=0; i<jobN; i++){
a[i]=i+1;
}
//Filling Order tab with Job order
JobS.fillLine(tabFillOrder, a, 0); //Fills the tab with the tab a (make a copy of it we could say)
//Reading the matrix line by line and filling tab line
for(int i=0; i<jobN; i++){
for(int j=0; j<toolN; j++){
String str = st.nextToken();
System.out.println(str);
tabFill[i][j] = Integer.parseInt(str);
}
line = br.readLine();
}
inputJobS.setJobS(tabFill);
br.close();
} catch (IOException e) {
System.out.println("File not found exception in inputJobMatrix.");
}
return inputJobS;
}
Which results in :
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(Unknown Source)
at pProgra.ReadJobS.inputJobMatrix(ReadJobS.java:84)
at pProgra.PPMain.main(PPMain.java:14)
I've tried looking for problems in my loops but didnt find any, and i can't understand why it doesn't work.
The goal here is to fill a bidimensionnal int array with the matrix of the input file (for exemple the one i've given previously with jobs and tools) and use that array for my object (JobS, i'll give the constructor here too if it can help) :
public class JobS {
private int[] jobOrder;
private int[][] jobS;
public JobS(int jobs, int tools){// Creates one more line for the title (jobOrder).
super();
int[][] tab = new int[jobs][tools];
int[] tab2 = new int[jobs];
this.jobS = tab;
this.jobOrder = tab2;
}
And the setter i use at the end:
public void setJobS(int[][] jobS) {
this.jobS = jobS;
}
I tried detailing the code as much as possible with comments, I hope you will understand what i want to do.
This is the first time i'm trying to do a "complex" application so maybe i'm just stupid and forgot something, but right now i've been searching for an hour and still have no clue what is causing this ..
Hope you can help, thanks in advance !
L.L.
as you can see the String line is empty:
String line = ""; // Line in tokenizer
so here st is empty:
StringTokenizer st = new StringTokenizer(line);
hence when you call this:
String str = st.nextToken();
an exception occurs.
ensure that the line has some data first, by instantiating the StringTokenizer after the for loop.
Example
change this:
StringTokenizer st = new StringTokenizer(line);
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
to this:
for(int i=0; i<3; i++){ //ReachFirstLine of matrix
line = br.readLine();
//System.out.println(line);
}
StringTokenizer st = new StringTokenizer(line);
side note - this code:
line = br.readLine();
will overwrite the value of line at each iteration within the loop, that could be what you wanted but if you want to append all the lines of text the readLine() gets then you can do this:
line += br.readLine();

Reading a text file into a 2D array

I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();

Read all lines from a text file and save each to it's strings (without using List)

I have a text file which is a game save for my java game (cookie clickers) so the stuff in the file will be numbers without spaces. Like so:
10
20
30
40
50
I need to read the lines and save each one to its string.
So the strings should be like this, so I can use them a lot easier:
lives = 10
kills = 20
score = 30
...
The saving code will be in its class file (Save.class). I only need the code, other stuff should not be a problem.
Is there some kind of easy way to make it work as I want?
You can use a Scanner as follows:
Scanner s = new Scanner(new File("your file"));
String lives = s.nextLine();
String kills = s.nextLine();
String score = s.nextLine();
...
s.close();
Scanner is good here.
List<String> list = new LinkedList<>();
Scanner scan = new Scanner(new File("the_file"));
while (scan.hasNextLine())
list.add(scan.nextLine());
I recommend you to use an ArrayList. Like this:
Scanner s = new Scanner(new File(//Here the path of your file));
ArrayList<String> list = new ArrayList<String>();
while (s.hasNext())
{
list.add(s.nextLine());
}
Now you will have stored all the lines of your file so you can access each of them like this:
for(int i = 0; i < list.size(); i++)
{
System.out.println("The content of the line " + i + " it's " + list.get(i);
}
I expect it will be helpful for you!
BufferedReader reader = new BufferedReader(new FileReader(FILE_PATH));
String line = null;
int index = 0;
while((line = reader.readLine()) != null) {
if(index == 0) {
line1 = line;
} else if(index == 1) {
line2 = line;
} else if(index == 2) {
line3 = line;
}
index++;
}
or you could read the text and save it as string array
also you might would like to use this http://ini4j.sourceforge.net
Use readAllLines:
File data = new File("textfile.txt");
List<String> lines = Files.readAllLines(data.toPath());
This way of saving game state smells. It seems that you're on your way on reinventing the wheel. Why don't you use a properties file where you can save the key(lives, kills, score) and the value ? It would make the code a lot more readable.
String gameStateFile = "gameState.properties";
Properties gameProperties = new Properties();
gameProperties.load(input);
String lives = gameProperties.get("lives");

Math.random and FileReader [duplicate]

This question already has an answer here:
BufferedReader skipping each second line
(1 answer)
Closed 8 years ago.
I'm trying to make a program which randomly get a line from a file, I have finished my code but I get weird results, for example if I get the line 0 it says "null" same with line 6, 7, 8, 9... but when I get number 5 I get last line (Pink), when I get number 4 I get line 7 (Brown), number 2 line 3 (Navy) and so on. My file "archivo.txt" has 10 lines like this:
Red
Orange
Blue
Navy
Lime
Green
Olive
Brown
Yellow
Pink
And this is my code:
public static String getLinea(){
File archivo = null;
FileReader fr = null;
BufferedReader br = null;
String linea = null;
int numeroRandom = (int)(Math.random() * 10);
System.out.println(numeroRandom);
try{
archivo = new File("C:\\archivo.txt");
fr = new FileReader (archivo);
br = new BufferedReader(fr);
for(int i = 0; i < numeroRandom; i++){
br.readLine();
linea = br.readLine();
}
}
catch(Exception e){
e.printStackTrace();
}finally{
try{
if(null != fr){
fr.close();
}
}catch(Exception e2){
e2.printStackTrace();
}
}
return linea;
}
public static void main(String[] args){
String linea;
linea = getLinea();
System.out.println(linea);
}
You are trying to readLine from the buffer two times in sequence.
for(int i = 0; i < numeroRandom; i++){
br.readLine();
linea = br.readLine();
}
instead just read once. Correct way :
for(int i = 0; i < numeroRandom; i++){
linea = br.readLine();
}
Also you should check if BufferedReader has any more data left before reading from the buffered reader. This can be done as follows:
while(((linea = br.readLine()) != null) && i < numeroRandom)
{
// do something
}
You are calling readLine() twice in your loop, effectively doubling the number of lines you are skipping.
I assume you want to read only the nth line, skipping the previous ones. Then you should update this piece of code:
br = new BufferedReader(fr);
for(int i = 0; i < numeroRandom; i++){
br.readLine();
linea = br.readLine();
}
Into this:
br = new BufferedReader(fr);
for(int i = 0; i < numeroRandom; i++){
br.readLine();
}
linea = br.readLine(); // move this line
You were getting null when numeroRandom was 0 because linea wasn't being updated. The other strange results happened because you were reading 2 lines in each cycle. There will be a point where getLine() will simply return null from not having more lines to read.

Categories

Resources