Solved

Unread a Line

Posted on 2002-06-19
14
240 Views
Last Modified: 2010-05-02
I have a sequential file open and using Line Input to read from it. Is there a way to "unread" a line in any way, so it can be Line Inputted again?

Thanks
0
Comment
Question by:afterburner
  • 5
  • 5
  • 4
14 Comments
 
LVL 22

Expert Comment

by:rspahitz
Comment Utility
The only way I know is to either close the file and re-open, then read that many characters, or use a binary open.  With a binary open, you can read any character string you want, but you have to parse it yourself to determine where the end of line is located.

BUT--Why not just store the line input string and use it whenever you need it?
0
 

Author Comment

by:afterburner
Comment Utility
Well its someone else's code and at the moment when it reads a file it uses a blank line in that file to signal the end of the reading for that particular section. I want it to use the flag line that starts the next section in the file being read to signal the end of the current section. Unfortunately, by the time this has been read in, the next routine which deals with the next section of the file has had its starting reference stolen by doing it this way, and there are several similar routines following along behind which read other sections of the file.
0
 
LVL 22

Accepted Solution

by:
rspahitz earned 50 total points
Comment Utility
Ouch...weak or overly patched design.

Again, the only way I know is to close the file, re-open it, and jump ahead to that part of the file.
0
 
LVL 8

Expert Comment

by:DennisBorg
Comment Utility
This is NOT the recommended way to process a file. To reread certain portions of the file can have a dramatic negative effect on efficiency.

However, you could always record the file position BEFORE reading the line, and if you need to reread that line, reposition the file pointer to the beginning of that line.

For example, assuming the following:

   Dim hFile   As Integer
   Dim FPos    As Long
   Dim strLine As String

   hFile = FreeFile()
   Open "somefile" For Input As #hFile
   FPos = Loc(hFile) 'Record the current file position
   'Read a line of text from the file
   Line Input #hFile, strLine
   Seek #hFile, FPos 'Set file pointer back to start of line
   'ReRead the same line again:
   Line Input #hFile, strLine
   Close #hFile


Again, to reread certain portions of the file is not the recommended course of action. But this is how you would go about doing so.

0
 

Author Comment

by:afterburner
Comment Utility
Hi DennisBorg
>Seek #hFile, FPos 'Set file pointer back to start of line

This would be the way I would do it too. But as I understand it, you cant access sequential files by byte positioning with Seek - you can only do that with Binary and Random access(?) But please correct me if I am wrong.
0
 
LVL 8

Expert Comment

by:DennisBorg
Comment Utility
  >as I understand it, you cant access sequential
   >files by byte positioning with Seek - you can
   >only do that with Binary and Random access(?)
   >But please correct me if I am wrong.

Before submitting my solution, I tried it out to make sure it would work with files opened in INPUT mode; and it worked just fine for me.
0
 
LVL 22

Expert Comment

by:rspahitz
Comment Utility
Yes.  I think there USED to be an issue/difference with files open for INPUT, BINARY or RANDOM ACCESS.  It seems that they all now support the same command set (although I haven't verified this.)
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 

Author Comment

by:afterburner
Comment Utility
> It seems that they all now support the same command set (although I haven't verified this.)


I forgot to mention that I am working back in VB 5, not 6 or later. Would I need to go to 6 to get that feature then?
0
 
LVL 22

Expert Comment

by:rspahitz
Comment Utility
I think it was the same in 5, but you should be able to try a simple experiment to find out.  Just use DennisBorg's example above on a test file.

0
 
LVL 8

Expert Comment

by:DennisBorg
Comment Utility
  >I think it was the same in 5, but
   >you should be able to try a simple
   >experiment to find out.  Just use
   >DennisBorg's example above on a test file.

I concur; to be certain, try it out on a test file. You could read the first 5 lines, and then try to read and reread the 6th line.

Be sure to let us know how it turns out.
0
 

Author Comment

by:afterburner
Comment Utility
The submitted solution does not work because fpos will return a byte position that is either random or based on the number of reads.

The only way to do this is to capture the length of the input lines and THEN do a Seek hFile, total_len_of_all_read_strLines.

Doing this, you have to add 2 for each read to allow for CR & LF.

OK, but this does not make use of Seek to read the position, only to set it. It cant be read usefully from a seq. file so you need to track string lengths. This isnt so clever because blank lines wtih CR LFs will cause a lot of pain.

0
 
LVL 22

Expert Comment

by:rspahitz
Comment Utility
I'd have to say that the request for unreading a line cannot be done.  Anything we offer will be a workaround, and likely a weak one because it tries to overcome a design flaw.

The real answer is to rewrite the offending component rather than to try to write a complex work-around.

(I'm sure that's not what you want to hear, but ultimately it will save you time and reduce future changes that add to the confusion.)
0
 
LVL 8

Expert Comment

by:DennisBorg
Comment Utility
  >The submitted solution does not work
   >because fpos will return a byte position
   >that is either random or based on the
   >number of reads.
   >
   >The only way to do this is to capture the
   >length of the input lines and THEN do a
   >Seek hFile, total_len_of_all_read_strLines.
   >
   >Doing this, you have to add 2 for each read
   >to allow for CR & LF.

This does not make sense to me. You would not have to calculate the length of each line at all. Neither does the LOC() function return a random number.

If the file is opened in Random Access mode, LOC() returns the record number of the most recent record that was read/written to the file.

If the file is opened Binary mode, LOC() returns the position of the last byte read or written.

If the file is opened in Sequential mode, LOC() returns the current byte position divided by 128.

The whole idea was to bookmark the CURRENT FILE POSITION *BEFORE* reading the line the first time. THEN read the line. If you should *then* realize you need to reread that same line, then simply return to your already-recorded position (by using Seek).


You would actually want to open the file in BINARY mode, instead of in SEQUENTIAL mode (OPEN FOR FOR INPUT opens the file for sequential access)


Find a text file (or make one) that has more than 300 lines of text in it. You will have to change the "C:\NetLog.txt" to the actual name of your file.

Then try the following code:

   Dim hFile As Integer
   Dim FPos  As Long
   Dim Buff  As String
   Dim Index As Long
   
   hFile = FreeFile() 'Get next available file handle
   Open "C:\NetLog.txt" For Binary As #hFile

   'Read the first 299 lines
   For Index = 1 To 299
      Line Input #hFile, Buff
   Next 'Index
   
   'Bookmark the 300th line BEFORE reading it:
   FPos = Loc(hFile) + 1

   'Read the 300th line for the FIRST time:
   Line Input #hFile, Buff
   MsgBox Buff '<--- Display the 300th line

   'Read the 300th line 9 more times:
   For Index = 1 To 9
      'Move the file pointer to the beginning
      'of the 300th line
      Seek #hFile, FPos
      'Read the 300th line again:
      Line Input #hFile, Buff
      MsgBox Buff '<--- Display the 300th line
   Next 'Index

   Close #hFile 'Close the file


Each time, the very same line is reread and displayed. Calculating the total length of all preceeding lines is not necessary.

0
 

Author Comment

by:afterburner
Comment Utility
I did ask for a solution to this when the file was open in sequential mode, however I admit I did not appreciate that it is possible to open a file in binary and then make sequential reads from it. If I had known it was that easy then I would have done it already.

The code I actually needed goes like this:


Private Sub Command1_Click()

  Dim hFile As Integer
  Dim FPos  As Long
  Dim Buff  As String
   
  hFile = FreeFile()
  Open "C:\somefile.txt" For Binary As #hFile

 
  Do While Buff <> "this line is the one I want to read again"
 
     
     Line Input #hFile, Buff
     FPos = Loc(hFile)
     
 
  Loop
 
 
     MsgBox Buff
     Seek #hFile, FPos - Len(Buff) - 1
     Line Input #hFile, Buff
     MsgBox Buff

  Close #hFile

End Sub


working on this file (c:\somefile.txt) as an example:

this is line number one
this is line number two
this is line number three
this is line number four
this is line five
this line is the one I want to read again
this is line seven
this is line number eight
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now