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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Remove trailing blank line in text file 6

Status
Not open for further replies.

BFarley

Programmer
May 22, 2008
43
US
I have a comma delimited text file from which I'm reading. After I work the contents of each line & determine it's not a blank line, I write that line into a new text file. So the new file is the same as the original, except any blank lines have been removed.

My problem is that there is always a blank line at the end of the new file. The program that uses this new text file raises an error if there is a trailing blank line.

My code:

Code:
Dim strInvLines() As String = {}

Dim sr As New StreamReader(strInputFileName)
            
Dim fileText As String = sr.ReadToEnd()
            
sr.Close()

strInvLines = Split(fileText, vbCrLf)

Dim fs As New FileStream(Path.Combine(My.Settings.OutputDirectory, strInputFileName), FileMode.Create)

Dim sw As New StreamWriter(fs)

For Each line As String In strInvLines
     If line.Length > 0 Then
          sw.WriteLine(line)
     End If
Next


sw.Close()
fs.Close()

Sample data:
Code:
20080523,0010079,RG,1,,BFE694200020035100,+,0144,.,45,+,002,00,+,0000288,.,89
20080620,0010079,RG,1,,BFE694200020035100,+,0144,.,45,+,006,00,+,0000866,.,67
20080627,0010079,RG,1,,BFE694200020035100,+,0144,.,44,+,005,00,+,0000722,.,22

Thanks so much in advance for your guidance.



Bryant Farley

"The Dude Abides
 
Reason you get the extra line is most likely to your Split on the vbCrLf. Simpliest fix for your code should be:

Code:
Dim strInvLines() As String = {}

Dim sr As New StreamReader(strInputFileName)
            
Dim fileText As String = sr.ReadToEnd()
            
sr.Close()

strInvLines = Split(fileText, vbCrLf)

[b][COLOR=red]Redim Preserve strInvLines(strInvLines.Count - 1)[/color][/b]

Dim fs As New FileStream(Path.Combine(My.Settings.OutputDirectory, strInputFileName), FileMode.Create)

Dim sw As New StreamWriter(fs)

For Each line As String In strInvLines
     If line.Length > 0 Then
          sw.WriteLine(line)
     End If
Next


sw.Close()
fs.Close()

The red piece should strip the last line out of the array. Typed and not tested.

You could also skip the reading the file into an array and just read it line by line instead. That would prevent the last "extra" line from being read in.

Code:
Dim fs As New FileStream(Path.Combine(My.Settings.OutputDirectory, strInputFileName), FileMode.Create)
Dim sw As New StreamWriter(fs)
Dim strLine As String = String.Empty
Using sr As New StreamReader(filename)
     Do
          strLine = sr.ReadLine()
          ' your logic and writeout goes here
          sw.WriteLine(strLine)
     Loop Until sr.EndOfStream
     sr.Close
End Using
sw.Close
fs.Close

=======================================
People think it must be fun to be a super genius, but they don't realize how hard it is to put up with all the idiots in the world. (Calvin from Calvin And Hobbs)

Robert L. Johnson III
CCNA, CCDA, MCSA, CNA, Net+, A+, CHDP
VB.NET Programmer
 
If I remember right writeline does a carriage return after writing the line. I think you have to use just write.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
Yes... Writeline does add a CR LF to the end of every line. You need to use write on the last line. Or use write and place your own CR LF at the end of each line except the last. The other option is to reopen the file after writing it and strip the last CR LF out of it.

"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
Using just write eliminates all carriage returns, not just the last one.

There will be occasions (hopefully the majority!) where the last line of the text file is in fact data, not just the carriage return. So ignoring the last line in all cases would not work.

Perhaps if I got the number of lines, instituted a counter, and for the last line used "write" instead of "writeline", that would address it?

Bryant Farley

"The Dude Abides
 
Perhaps if I got the number of lines, instituted a counter, and for the last line used "write" instead of "writeline", that would address it?
Yes, we were talking about something like that. Or you could switch from a for each to a for count loop and watch for the last line that way as well.

-I hate Microsoft!
-Forever and always forward.
-My kingdom for a edit button!
 
OUSoonerjoe ... what's the best way to strip the last CRLF as you suggested?

Bryant Farley

"The Dude Abides
 
I would personally use :
Code:
For x = 0 to RecordCount Step 1
if x = RecordCount then
     .Write (StringData)
Else
     .WriteLine (StringData)
End IF
Next x

Reopening the file takes more time and doubles the work. If you can just get a RecordCount and step through it, you hit the file once and that's that. If your file happens to get too big, it'll hit the system pretty hard and lock it up while trying to re-open. If you just use the existing stream and control what is flowing out of it, your process will run faster and in turn make the users happier.

if you really insist on re-opening:
- keep track of the number of records writing out.
- re-write the file as shown above.

Or call a UNIX tool called grep to strip the last 2 characters out. I think Awk might be able to do it, but it's been a while since I've used it.


"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
Thinking back on the original problem......what about this:

Code:
        Dim fs As New FileStream(Path.Combine(My.Settings.OutputDirectory, strInputFileName), FileMode.Create)
        Dim sw As New StreamWriter(fs)

        Dim strLine As String = String.Empty
        Using sr As New StreamReader(strInputFileName)
            strLine = sr.ReadLine
            If sr.Peek > -1 Then
                sw.WriteLine(strLine)
            Else
                sw.Write(strLine)
            End If
            sr.Close()
        End Using

        sw.Close()
        fs.Close()

We begin by opening the write file. Then we open the read file and loop through it line by line. using the .Peek method, if there is another line after the current, we use WriteLine. If there are no more lines, we use the Write method instead. Finally close and save all files.

Typed and not tested....

=======================================
People think it must be fun to be a super genius, but they don't realize how hard it is to put up with all the idiots in the world. (Calvin from Calvin And Hobbs)

Robert L. Johnson III
CCNA, CCDA, MCSA, CNA, Net+, A+, CHDP
VB.NET Programmer
 
Forgot the loop :(

Code:
        Dim fs As New FileStream(Path.Combine(My.Settings.OutputDirectory, strInputFileName), FileMode.Create)
        Dim sw As New StreamWriter(fs)

        Dim strLine As String = String.Empty
        Using sr As New StreamReader(strInputFileName)
            Do Until sr.EndOfStream
                strLine = sr.ReadLine
                If sr.Peek > -1 Then
                    sw.WriteLine(strLine)
                Else
                    sw.Write(strLine)
                End If
            Loop
            sr.Close()
        End Using

        sw.Close()
        fs.Close()


I tested this and it seems to work as expected....let me know.

=======================================
People think it must be fun to be a super genius, but they don't realize how hard it is to put up with all the idiots in the world. (Calvin from Calvin And Hobbs)

Robert L. Johnson III
CCNA, CCDA, MCSA, CNA, Net+, A+, CHDP
VB.NET Programmer
 
Here's another way to avoid the extra blank line:
Code:
Dim CrLf As String = String.Empty
For Each line As String In strInvLines
    If line.Length > 0 Then
        sw.Write(CrLf & line)
        CrLf = vbCrLf
    End If
Next
 
That's an interesting way to get there, Dave. I like it. The first iteration does not have the vbCrLf defined at the beginning. Sweet and Simple.

BFarley, you have your simplest answer from Dave.

"If I were to wake up with my head sewn to the carpet, I wouldn't be more surprised than I am right now.
 
Very effective solution that works like a charm!

Thanks DaveInIowa and also everyone else that contributed their valued insight.

Bryant Farley

"The Dude Abides
 
Nice answer Dave. Clean and to the point.

=======================================
People think it must be fun to be a super genius, but they don't realize how hard it is to put up with all the idiots in the world. (Calvin from Calvin And Hobbs)

Robert L. Johnson III
CCNA, CCDA, MCSA, CNA, Net+, A+, CHDP
VB.NET Programmer
 
Thanks everyone. I use this technique frequently to convert an array or collection to a separated list of values:
Code:
Dim CsvList As String = String.Empty
Dim CommaSpace As String = String.Empty
For Each thing In things
    CsvList &= CommaSpace & thing
    CommaSpace = ", "
Next
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top