Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Can RandomAccessFile pointer point to specific line?  RSS feed

 
Matt Senecal
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In looking at the specs for RandomAccessFile, I see that you can place the file pointer at any point in the file by specifying which byte you want to point to.
I need to be able to position the pointer at the start of a specific line. I do know how many lines the file has, but not how many bytes, so specifying by byte is a non-option. Is there any way to do this?
 
Michael Hildner
Ranch Hand
Posts: 297
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't think a RandomAccessFile has any concept of a 'line', since it is dealing with a sequential sequence of bytes. You could know what the end of line marker is, then as you read through, you would know what 'line' you're at.
Alternatively, maybe a BufferedReader, readLine until you get to the line you want, then a String.substring() to get the character. Writing to this position is a different story though.
 
ramesh gutty
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Matt,
I think you can do this easily. The java.io.RandomAccessFile class provides a readLine() method. Just refer to the javadocs ;-)
Regards,
Ramesh gutty :-)
 
Michael Hildner
Ranch Hand
Posts: 297
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're right about that, ramesh, my bad
 
Matt Senecal
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, this method doesn't do what I need. I read the javadocs very carefully before I posted my question.
According to the documentation, the readLine() method in RandomAccessFile reads the "next line of text from this file". I don't need to read the next line, I need to be able to jump to any given line at random.
Now, obviously, if I know how many lines there are in the file I can do multiple readLine() until I reach the line I need to look at. But that's woefully inefficient when you're working with a file that contains 100,000+ lines (as I am), and will be reading lines from the file at random.
Originally posted by ramesh gutty:
Hi Matt,
I think you can do this easily. The java.io.RandomAccessFile class provides a readLine() method. Just refer to the javadocs ;-)
Regards,
Ramesh gutty :-)

 
ramesh gutty
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Hi Matt,
If you you want to only read the file, then here is a fast implementation I wrote. This class extends the
RandomAccessFile (RAF), (so that it can be casted to RAF and passed around). Internally it stores the lines
read in a collection (I have used HashMap, but you can use any collection). The readLine()
method is final in RAF, so it delegates calls to this method. This method is smart enough to not read the file,
if the line has been already ready, otherwise it reads and returns the required line.
You can modify this for file updation (basically you need to refresh the cache), if the file has very low chances
of updation
import java.io.*;
import java.util.*;
//This class extends RandomAccessFile so that it can be casted to RandomAccessFile
public class FastReader extends RandomAccessFile {
private HashMap fileContents = new HashMap(); //load factor, increment can be optimized;
//in fact we can use and collection here
private int lastLineRead = 0;
private long curPosition = 0;
public FastReader(String name, String mode) throws FileNotFoundException
{
super(name, mode);
}
public FastReader(File file, String mode) throws FileNotFoundException, IOException
{
super(file, mode);
}
//This method returns null, if eof is reached before the line number. lineNumber starts from 1, so if
//you call this method with argument with '1' you should see the first line
public String readLine(int lineNumber) throws IOException
{
if (lineNumber < 0) throw new IOException("Line number cannot be negative");<br /> //Check if we have read the linenumber till now, if so return the line directly<br /> if (lastLineRead >= lineNumber) {
return (String)fileContents.get(new Integer(lineNumber));
}
seek(curPosition);
while (lastLineRead < lineNumber) {
lastLineRead++;
fileContents.put(new Integer(lastLineRead),readLine());
}
curPosition = getFilePointer();
return (String)fileContents.get(new Integer(lastLineRead));
}
}
lemme know if this helps....
Regards,
Ramesh gutty :-)
 
Frank Carver
Sheriff
Posts: 6920
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Or if the file really is too big, then you just need to generate an index. This is especially useful if the file doesn't change very often (very big text files usually don't, unless they are something like a log file which just appends new lines).
Write a simple sequential reader which whizzes through the file noting the byte at which each line starts, then either store that "array" in memory if it's small enough, or in another RAF. If you store it in a file, make sure that each element has the same number of bytes, so access is quick with no searching.
Then to read line 1045 (say), just access element 1045 of the index, then go to that point in the main RAF, and read the next line as mentioned in a previous reply. Seems pretty quick and simple to me. It's what us old-timers used to do before we had commodity databases and SQL. Ever run "fortune" on a Unix system?
 
Matt Senecal
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, guys!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!