Win a copy of Kotlin in Action this week in the Kotlin forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Read prev line in the file?  RSS feed

 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I'm trying to write an application, which reads data from a txt file. It reads one line, splits the line at "/" and displays the two split parts of this line in two text areas. I have a Back and a Next button in the panel, which should show previous/next line in the text areas, when clicked.

I've been looking through documentation. After going through several classes, I found a class LineNumberReader, which I thought was what I needed, but when I read the description, I was disappointed. It says -


A buffered character-input stream that keeps track of line numbers. This class defines methods void setLineNumber(int) and int getLineNumber() for setting and getting the current line number respectively.

By default, line numbering begins at 0. This number increments as data is read, and can be changed with a call to setLineNumber(int). Note however, that setLineNumber(int) does not actually change the current position in the stream; it only changes the value that will be returned by getLineNumber().


So it doesn't take the cursor back to the previous line, it merely changes the number. I wanted to know whether there IS any such class, which will let me read previous/next line? Any help will be really useful, thanks in advance!
 
Ulf Dittmer
Rancher
Posts: 42972
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Java class libraries have no such class. While one could be written, maybe a better option would be to read the file contents into memory (maybe store them in a List with one line of input per element). That way there wouldn't need to be file I/O for each previous/next operation.

How big are the files?
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Thank you for reply. Well, the files are not very big. Just a small text file, where each line contains something as follows -

Question1/Option1/Option2/Option3/Option4

So, I want to get each question in the text area and the Back button should so previous question (i.w. previous line) and Next button should show Next line etc. Well, I searched some more and am thinking may be RandomAccessFile could be helpful. But I don't know how to use it. Which reader takes RandomAccessFile as an argument? I was previously working with BufferedReader, which apparently doesn't take RandomAccessFile. I searched for codes, which use RandomAccessFile, but haven't found anything useful so far. Any suggestions as to which reader to use?
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Er, I think I don't need any reader.. the RandomAccessClass has readLine() method! I'll go and try it out.

EDIT: Well, tried it.. but getFilePointer() seems to return character-wise or byte-wise position rather than something like line number. So I'm still stuck, since the lines in my text file are not of the same length.

So I still need some help with that problem. Any pointers as to which class can be used to solve this, are appreciated. Thanks in advance!
[ June 06, 2008: Message edited by: Roshni Singhania ]
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you happen to try the PushBackReader class?
It seems to do what you want, however, at the creation of the reader you would have to specify, how many maximum number of characters you can push back.
Also, when you read the line, you must know how many characters it consists of to push it back(PushBackReader can only push back character arrays and not lines, as it does not have a notion of a line.)
This article has an example and sample code to use the PushBackReader.
If you find it useful, do let us know.
 
Rob Spoor
Sheriff
Posts: 21092
85
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ulf has given you a perfectly good answer - first read in the entire file, adding all lines to a List, then use its listIterator() method to get a ListIterator. With this, you can go both forward and back.
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

Thanks for the answers. I'm sorry but I don't understand one small part - How would I know the number of characters in each line (i.e. number of characters to push back, if I'm not mistaken?) if each line is of different length? Or have I not understood it properly? I get a little confused when the things like "offset" and char[] come into picture, so please don't flame me!

I was also trying another way to get around my problem, but in that case, I'm getting "Stream not marked" exception. I tried overriding BufferedReader/FileReader class, no use. How exactly do you make your stream "markSupported"??

EDIT: Corrected a spelling mistake.
[ June 06, 2008: Message edited by: Roshni Singhania ]
 
Joe Ess
Bartender
Posts: 9429
12
Linux Mac OS X Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Roshni Singhania:
I'm sorry but I don't understand one small part - How would I know the number of characters in each line

You don't. The number you provide is the maximum size of the pushback buffer, the greatest number of characters you can push back. All the PushBackReader does is store what you've read in a buffer so you can read it again. Since this buffer can get pretty large, you have to provide a max. size.

Originally posted by Roshni Singhania:
I'm getting "Stream not marked" exception.
[/QB]


You have to invoke mark() on a stream before you can roll it back. mark() tells the PushBackReader to start recording data.
I agree with Rob. Ulf's solution is best.
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

I was trying to work out a solution using ArrayList and it's pretty much working. Except one small glitch. When I reach the last question in the list, say question3, I have to press Back button twice to go back to question1, then I press Back button once and it goes to question1. Same thing when going ahead - I have to press Next button twice to go from Q1 to Q2, but then I need to press it only once to go from Q2 to Q3. I tried everything since last evening, but I'm just not able to figure out what's wrong with the logic. Other than having press Back and Next twice when at the end or at the beginning of list, things are working the way I want.

Here's what I'm trying to do in the Back and Next button listeners -



getData() is called only once when the application is loaded, to populate the strList and thereafter only the button listeners and fillData() is being called. Qno is merely to show the number on the label. Is this code enough to point out the flaw or should I post whole code? I've been trying every different way to set the index variable properly but I don't know what I'm doing wrong that it's taking two button clicks! I'll really appreciate any pointers as to what I'm doing wrong in above code. Thanks in advance.

I haven't yet tried using PushBackReader, since I was stuck with this problem since last evening. Will go and try it now.
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A quick question about PushbackReader. How do you read one line at a time with PushbackReader when the number of characters in each line is not fixed? Is there any way to tell it to go on next line when it encounters "\n". I didn't find anything in the documentation of PushbackReader that would solve this doubt. I thought may be mark() could be useful, but then again, how do you mark the end of the line.

I've done something line this -



What goes in place of the question mark?? How do I make sure that it'll read one line at a time and then go to next line and so on? And with offset specified as 0, it'll start from the beginning of the file, then how does it go on the next line.. what would be the offset value for that? I'm quite lost here!
 
Ulf Dittmer
Rancher
Posts: 42972
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would change the signature of the fillData method from "void fillData (String[] strArr)" to "void fillData (int index)", and move the "strArr = strList.get(index).split("/")" line into it. Note how that line is now present in several places?

If you then put a "System.out.println(index)" at the beginning of that method, I bet you'll find the flaw in the logic pretty quickly.

As an aside, don't bother with PushBackReader; it's an unnecessarily complex solution for this problem.
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ulf Dittmer,

Thank you SOOO much for pointing that out! Yes some lines of code were repeated at 2-3 places. And I was having trouble with that "index number repeating" issue since yesterday! I'd shuffled index variable around a lot, trying out pre/post increment/decrement in different lines, but I just couldn't get it to work. So after you pointed out the repeated lines of code, I first fixed that part and then it was easier to keep track of the index variable's values. So that was a huge help! Oh, then my new logic created a new problem, which I fixed by just disabling the Back/Next buttons when they reached the lower/upper limit

Here's what I did -



So now it's working as I wanted it to. Thank you sooo much!!!


About PushbackReader class, I again went through the link you'd previously given, and this time I understood it better. But a couple of questions still remain. I'd appreciate any guidance regarding those.

1) Can we do something like read a char and check whether its "\n", so that we can keep reading all the characters till the "\n" is reached? Will that help in reading one line at a time? (I'm going to try it out, but I just wanted to know whether it's feasible when you're reading one (non-fixed-length) line at a time from a file.)

2) And how do we specify that we want it to read from the next line thereafter?
 
Ulf Dittmer
Rancher
Posts: 42972
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Glad you got it working. A couple of comments:

- The "Qno" variable seems unnecessary. Just write lblQno.setText("Question Number " + (index+1)). That's also one fewer instance variable to keep track of.

- I never use prefix/postfix incrementors (like ++Qno) in an expression. It's just too easy to introduce hard to detect bugs, and it's also harder to read. I always put them on separate lines. The next developer looking at this code will thank you (as will you, once you haven't looked at it in a year).

- The button en-/disabling looks incomplete. If the "Next" button is clicked on the first question, then the "Previous" button should get enabled; same when clicking "Previous" on the last question. Are you handling this somewhere else? If so, move the code into the action listeners as well; it should all be in one place.

- The checks for "if(index<strList.size())" and "if(index>=0)" are now unnecessary, since they will always be true.
 
Roshni Singhania
Ranch Hand
Posts: 78
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Ulf Dittmer:
Glad you got it working. A couple of comments:

- The "Qno" variable seems unnecessary. Just write lblQno.setText("Question Number " + (index+1)). That's also one fewer instance variable to keep track of.

- I never use prefix/postfix incrementors (like ++Qno) in an expression. It's just too easy to introduce hard to detect bugs, and it's also harder to read. I always put them on separate lines. The next developer looking at this code will thank you (as will you, once you haven't looked at it in a year).

- The button en-/disabling looks incomplete. If the "Next" button is clicked on the first question, then the "Previous" button should get enabled; same when clicking "Previous" on the last question. Are you handling this somewhere else? If so, move the code into the action listeners as well; it should all be in one place.

- The checks for "if(index<strList.size())" and "if(index>=0)" are now unnecessary, since they will always be true.



Hi, thank you very much for the comments.

Yes, Qno was introduced as a result of my confusion as to why the index variable was "misbehaving"; I decided to keep the two things separate while trying to debug the code. It's no longer required. And same about the unnecessary "if" checks, although I hadn't realized about that one till you pointed it out.

Yeah, I was making that mistake of using pre/post increment/decrement operators as a part of expression. You're right, putting them on individual lines did help me a lot.

About button en-/disabling, that's the only code for doing that and I thought it was working fine, but when you pointed it out, I tested it again; yes, it needs to be fixed. It works when I go from 1-2-3, but if I go 1-2-1, it doesn't. Will try to fix it.

Thank you for pointing all this out. That was very kind of you. I'll go and make the remaining corrections. Thanks again!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!