Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Start Read Text file from specified position? 2

Status
Not open for further replies.

ahnugroho

Programmer
Jan 29, 2003
45
ID
I create Windows Application on BV .net to monitor transaction file (text file), if match with criteria then do something.

I use StreamReader to read the file. but i am stuck how to read the file start from the last read position after my application is stopped.

Please help me!

rgds
ahnugroho


 
You can save the last position somewhere by
StreamReader.BaseStream.Position
and then seek to this point before reading
StreamReader.BaseStream.Seek(pos, SeekOrigin.Begin)
 
thanks korach,
it's working.
but is it possible to make sure that the position is pick up when Reading the line is completed.

this is the code after modified from you

Imports System.IO
Public Class frmMonArchive
Inherits System.Windows.Forms.Form
Dim sFile As StreamReader
Dim sLine As String
Dim iSec As Integer
Dim LastPosition As Integer
Dim Status As Boolean
Dim RecNo As Integer

'Timer 1

Private Sub Tm1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Tm1.Tick

'check lines every second

lblTime.Text = System.DateTime.Now.ToLongTimeString
iSec = System.DateTime.Now.Second

If Status = True Then
sLine = sFile.ReadLine

If sLine <> Nothing And sLine.Substring(1, 4) = "POMT" Then
'write to another text file
FileOpen(1, "D:\CMS\NEW-POMT.FIL", OpenMode.Append)
PrintLine(1, sLine)
FileClose(1)
End If
lblLastLine.Text = sLine
LastPosition = sFile.BaseStream.Position
End If


End Sub


Private Sub frmMonArchive_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Status = False
End Sub

'Start Button

Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStart.Click
sFile = New StreamReader("D:\CMS\POMT")
If LastPosition <> 0 Then sFile.BaseStream.Seek(LastPosition, SeekOrigin.Begin)
'lblLast.Text = sLine
Status = True
End Sub

'Stop Button

Private Sub cmdStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStop.Click
Status = False
LastPosition = sFile.BaseStream.Position
MessageBox.Show(sFile.Peek.ToString)
sFile.Close()
End Sub
End Class

base on the code above, when I stop reading the file and get the last position. sometimes the last position is in the midle of line text. so, when I started again, this record is skipped.

thanks
 
I don't see how you can stop in a middle of a line if you always do ReadLine(). The file position will always be in a row ending.
 
You're right Korach!

after debugging, I found that return value StreamReader.BaseStream.Position is increment value from 1024. eg. 1024,2048,3072,4096....

this is not the real position on the file.
So, I have to try another way. or you may have another idea?



 
I think it is the real position in the file. Maybe your line length is 1024 bytes?
I didn't understand from your code what exactly you want to do. try to explain it and I will try to find a way.
 
thanks for your help
the line length is vary.

I have Timer on the form.
On Tick event there is code to read line in the text file then append the line to another file.

I have 2 button Start and Stop.
Start button will change the Status to TRUE then the code int the Timer (on TICK event) that Read the file and Write to another file will run.

Stop button will set Status to FALSE, so the code on Timer (TICK event) will do nothing.

When stop button is clicked, then I have to pick up the Last Position of file in reading, then the value will be used to Start reading the file.

thanks
 
Sounds like the StreamReader reads a whole block off the disk, and buffers it. The ReadLine just gets the data out of the buffer.
 
thank you for all your help.

I use another methode to get the last position.
Count the text lines (LastPosition) then the value will be used for next checking.

code:
Do
sLine = sFile.ReadLine()
CurrentRec = CurrentRec + 1
Loop Until LastPosition = CurrentRec

but this methode is not the best way if a thousand of line is to be check.

thanks
 
Well, you're right. The stream position is incremented by 1024, sorry.
I have another idea and this is the code:
Code:
    Dim sFile As StreamReader
    Dim wFile As StreamWriter
    Dim sLine As String
    Dim LastPosition As Integer = 0

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)

        lblTime.Text = System.DateTime.Now.ToLongTimeString

        sLine = sFile.ReadLine

        If sLine <> Nothing Then

            wFile.WriteLine(sLine)

        End If

        lblLastLine.Text = sLine
        LastPosition += sLine.Length + 2
        lblPosition.Text = LastPosition.ToString

    End Sub

    Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStart.Click

        sFile = New StreamReader("C:\source.txt")
        wFile = New StreamWriter("C:\target.txt", True)
        sFile.BaseStream.Seek(LastPosition, SeekOrigin.Begin)
        AddHandler Timer1.Tick, AddressOf Me.Timer1_Tick

    End Sub

    Private Sub cmdStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStop.Click

        RemoveHandler Timer1.Tick, AddressOf Me.Timer1_Tick
        sFile.Close()
        wFile.Close()

    End Sub
Don't use the old vb functions. Move to .NET.
You don't have to declare a status variable. Connect and disconnect the tick event when the user press the start and stop.
My code counts the position in the file by counting the string length. I added 2 to the length because each line has two chars and the end, representing the line ending, and String.Length or ReadLine ignores them. Some files use only one char for line ending like unix files.
 
Thanks so much ahnugroho, for the question. I think I learn more by reading posts then posting.
To get the answer you want, you need to know the right question.

And korach, you got a star from me too. I never knew it was possible to read from a position in a text file.
So I need to store the seek varable in an ini file or something between exe runs.
 
Thanks Korach, it's working fine.

I just try .Net 2 months ago. and sometimes the code mixed up with old VB.
another problem comes up.
the text file is locked during reading or open.

Do you have any idea to make the file currently read is not locked, so another application can write to it?

I found the methode on FileStream, but still no idea to do it!

Bigfoot: thanks for the tips.
my english not so good, may be not easy to understand.
 
Maybe you tried the "unlock" method. I don't think this is what you need. I assume this allows other threads to access the stream itself, not the file.

The way to do it is to allow sharing:
Code:
Dim f As FileStream = New FileStream("C:\tmp.txt", FileMode.Open, FileAccess.Read, FileShare.Write)
sFile = New StreamReader(f)
I tried it and it works fine. If you want to try it yourself, open two projects. One will read and the other will write. You don't have to enable sharing in both applications, but make sure the application that enables sharing will open the file before the other application.
You don't have to declare the FileStream variable in the class level, since it will be kept by the StreamReader.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top