Java - Random line read
Asked Answered
G

4

8

I am programing an Android app, and would like my program to read a random line of a file. How would I go about doing that?

Gulgee answered 24/1, 2011 at 18:27 Comment(0)
O
4

To do that, you need either fixed-length lines (the implementation details should be obvious in that case) or information about how many lines there are and (optionally, for better performance) at what offsets inside the file they begin (an index of sorts).

For small files, you can create such an index on demand whenever you need a random line. To do it efficiently for large files, you need to keep the index around persistently, perhaps in a separate file.

If lines tend to be roughly the same length and you don't need perfect "randomness", you could also pick a random byte offset inside the file and scan for the nearest line break.

Olden answered 24/1, 2011 at 18:33 Comment(3)
That was actually my plan. Could you give me more info as to why the lines must be fixed-length? I will just have a .txt file (or .bin whatever).Gulgee
@Walter: If lines have the fixed length of N bytes (beware encoding issues!) and the file has size S, then there are S/N lines and line number X begins at byte offset X*N. Jumping to a given byte offset in a file is both easy and efficient.Olden
@ Michael: That makes sense - Though that seems like more work than it's worth, If you just had a function that ran at the initiation (or have the first line in the file contain the number of lines)Gulgee
P
8

What you want is a LineNumberReader.

You can use the method setLineNumber() to move to a random position in the file.

LineNumberReader rdr;
int numLines;
Random r = new Random();
rdr.setLineNumber(r.nextInt(numLines));
String theLine = rdr.readLine();
Pennyroyal answered 24/1, 2011 at 18:30 Comment(12)
+1. That is a much better answer than I was about to give. I had no idea that class existed.Akerley
@McStretch, thanks. The class is super useful for this kind of operation. (But usually there are better classes to use)Pennyroyal
This definitely works but you really have to keep in mind that every line read means reading all the lines between the beginning of the file and that line.Gilly
@McStretch: you may want to first consider the question "where and how is numLines calculated?".Olden
That code should be exactly what you need, as long as you set the numLines variable appropriately- is there any nice way to ask a file how many lines it has?Shockey
@Michael, at worst the file can be traversed once to count the lines. Then it can be used going forward. (Unless you are using a different file each time)Pennyroyal
@Jems: no, there isn't. Basically, you have to count the number of line breaks in the file. Not something you want to do on demand for a large file.Olden
@Toad, you will always have to read/skip bytes in a file to get to the location you want.Pennyroyal
@Michael: Very true. I posted my comment regarding LineNumberReader, which was posted before Justin's code example. I was going to post a link to a similar question that contained various answers regarding how to get the amount of lines.Akerley
This discussion touches on another reason I posted this question: I want to have the program use the least resources - due to the nature of android.Gulgee
@Justin True but skipping can be done efficiently (since you have more information) while reading all the bytes can't really be done efficiently. If he can prepare the file before packaging the application he can put some sort of index near it to make sure he can do the skipping.Gilly
@Pennyroyal if this thread is active: can you check #39033590Isla
O
4

To do that, you need either fixed-length lines (the implementation details should be obvious in that case) or information about how many lines there are and (optionally, for better performance) at what offsets inside the file they begin (an index of sorts).

For small files, you can create such an index on demand whenever you need a random line. To do it efficiently for large files, you need to keep the index around persistently, perhaps in a separate file.

If lines tend to be roughly the same length and you don't need perfect "randomness", you could also pick a random byte offset inside the file and scan for the nearest line break.

Olden answered 24/1, 2011 at 18:33 Comment(3)
That was actually my plan. Could you give me more info as to why the lines must be fixed-length? I will just have a .txt file (or .bin whatever).Gulgee
@Walter: If lines have the fixed length of N bytes (beware encoding issues!) and the file has size S, then there are S/N lines and line number X begins at byte offset X*N. Jumping to a given byte offset in a file is both easy and efficient.Olden
@ Michael: That makes sense - Though that seems like more work than it's worth, If you just had a function that ran at the initiation (or have the first line in the file contain the number of lines)Gulgee
W
2

An old fashioned answer: If you get back a null, just recall the method

BufferedReader br = new BufferedReader(file);
Random rng = new Random (8732467834324L);
String s = br.readLine();
for ( ; s != null ; s = br.readLine())
    if (rng.nextDouble() < 0.2)
        break;
br.close();
return s;
Waldenses answered 24/1, 2011 at 18:43 Comment(0)
L
1

to obtain a random number you can use java's Random class from the util package.

Random rnd = new Random();
int nextRandomLineNumber = rnd.nextInt();

see http://developer.android.com/reference/java/util/Random.html

Lisk answered 24/1, 2011 at 18:36 Comment(3)
The only problem I see with this is: there are no bounds set for the Random()Gulgee
You'd set the bounds by using the other nextInt() method, nextInt(int n): "Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive), drawn from this random number generator's sequence."Akerley
yes, i just wanted to show him that class, wich nextInt(int x) he then would get an int between 0 and x. at the time i finished my post, the first answer was already corrected (first there was only the comment about setLineNumber without thr random object)Lisk

© 2022 - 2024 — McMap. All rights reserved.