InputStreamReader and reading random lines from .txt file
Asked Answered
G

5

1

I have a method for my app to read a random line from a text file and return it. Im using the randTxt() to read and return a random line from the txt file. but it only shows the same line (1st line) everytime.

public String randTxt(){

  // Read in the file into a list of strings
  InputStreamReader inputStream = new InputStreamReader(getResources().openRawResource(R.raw.randomstuff));
  //ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

  String theLine="";
  int i;
  try {
    i = inputStream.read();
    while (i != -1) {
      i = inputStream.read();
    }
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }

  LineNumberReader  rdr = new LineNumberReader(inputStream);
  int numLines = 30;
  Random r = new Random();
  rdr.setLineNumber(r.nextInt(numLines));

  try {
    theLine = rdr.readLine();
  } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
  }

  return theLine;
}

How can I fix it? and Can someone explain what's wrong in my code?

Glidebomb answered 2/1, 2012 at 19:57 Comment(1)
What did you learn when you stepped through your code in the debugger?Scleroprotein
R
3

Here's the framework for doing what you need using BufferedReader. In this case, you don't need to store the values in a temp array.

InputStreamReader inputStream = new InputStreamReader
  (getResources().openRawResource(R.raw.randomstuff));
BufferedReader br = new BufferedReader(inputStream);
int numLines = 30;
Random r = new Random();
int desiredLine = r.nextInt(numLines);

String theLine="";
int lineCtr = 0;
while ((theLine = br.readLine()) != null)   {
  if (lineCtr == desiredLine) {
    break;
  }
  lineCtr++;
 }
...
Log.d(TAG, "Magic line is: " +theLine);
Refractive answered 2/1, 2012 at 20:44 Comment(2)
Thanks I've tried it but it has an error I've been trying to fix: BufferedReader br = new BufferedReader(new InputStreamReader (inputStream, "UTF-8")); Error: The constructor InputStreamReader(InputStringReader,String) is undefined.Glidebomb
Whoops, I believe that should have been "BufferedReader br = new BufferedReader(inputStream)". I've edited it - can you try now?Refractive
P
3

You have gotten an answer of how to fix your code, but no explanation of why our original code did not work.

LineNumberReader.setLineNumber(int) does not go to the actual line, it just changes what number you call the current line.

So, say you read two lines, getLineNumber() will now return 2 (it started at 0 and increased by 1 each time a newline was encountered). if you now setLineNumber(10), getLineNumber() will return 10. Reading yet another line (your third) will cause getLineNumber() to return 11.

This is described in the Java Doc.

Pyrochemical answered 2/1, 2012 at 22:11 Comment(1)
Thanks, I was too excited I guess :DGlidebomb
B
2

inputStream.read does not return a line number. it returns the byte that was read. this isn't how you would read line by line. to read line by line, you should use buffered reader's readLine method. its probably easier at that point to read it all into a local array and use that array to randomly get an entry, rather than using a line number reader.

Bravin answered 2/1, 2012 at 20:3 Comment(4)
my text file has long Strings. I think it's not a good idea to load it into an array.Glidebomb
Is the number of lines in the file static or dynamic? if its static, you can just use that as a basis. Since this is android, why not just put the content of the file in the sqllite database?Bravin
Looking a bit more, take a look here if you want to see a faster way to count the # of lines in a file: #453518Bravin
It's static.. Because I'm just a beginner, I haven't worked with sqlite at all.Glidebomb
F
0

I think Random() function returns a value between 0 and 1. hence, you may have to multiply it with 100 to get an integer value. May even consider a MOD "your upper limit" operation to guarentee that the index you finally get is between 0 and your upper limit

Use the index you calculated thus, in your setLineNumber() method.

Edit: As john said, we can get whole number using Random() object.

Flowing answered 2/1, 2012 at 20:2 Comment(2)
But I'm using nextInt(n), which returns an integer between 0 to n.Glidebomb
No, random.nextInt(int) returns whole numbers. you do not need to mod or multiply anything. docs.oracle.com/javase/6/docs/api/java/util/…Bravin
J
0
public String getRandomLine(String fileLoc) throws IOException
{
    BufferedReader reader = new BufferedReader(new FileReader(fileLoc));
    ArrayList<String> lines = new ArrayList<String>();

    String line =null;
    while( (line = reader.readLine())!= null ) 
        lines.add(line);

    // Choose a random one from the list
    return lines.get(new Random().nextInt(lines.size()));
}
public String getRandomLineOpt(String fileLoc)throws IOException
{
    File f=new File(fileLoc);
    RandomAccessFile rcf=new RandomAccessFile(f, "r");
    long rand = (long)(new Random().nextDouble()*f.length());
    rcf.seek(rand);
    rcf.readLine();
    return rcf.readLine();
}
Joe answered 13/2, 2013 at 15:19 Comment(1)
Thanks for posting an answer! While a code snippet could answer the question it's still great to add some addition information around, like explain, etc ..Pratte

© 2022 - 2024 — McMap. All rights reserved.