claudebl
claudebl

Reputation: 75

How to remove a blank line at the end of a text file after deleting a line?

I borrowed four lines of code from Stack Overflow, regarding removing a specific line from my text file in vb.net. Here they are:

 Dim delLine As Integer = 4
 Dim lines As List (Of String) = File.ReadAllLines ("c:\essai.librarie", Encoding.UTF8).ToList()
 lines.RemoveAt(delLine - 1)
 File.WriteAllLines("c:\outfile.librairie", lines, Encoding.UTF8)

It works fine but after deleting my line 4, I have an empty line in the last position of the file with the number 11! (see screenshot).

How to avoid this blank line?

enter image description here

Upvotes: 1

Views: 736

Answers (1)

Jimi
Jimi

Reputation: 32288

File.WriteAllLines() add a line terminator - defined by the protected CoreNewLine Field in the base class, TextWriter, and returned by the TextWriter.NewLine virtual property - to each line it writes, including the last.

You have different method to remove this terminator:

Imports System.IO

Dim sourcePath = Path.Combine([Source Path], "SomeFile.txt")
Dim destinationPath = Path.Combine([Dstination Path], "SomeOtherFile.txt")
Dim lineToDelete As Integer = 3

Dim lines As List(Of String) = File.ReadAllLines(sourcePath, Encoding.UTF8).ToList()
lines.RemoveAt(lineToDelete - 1)

▶ Simplified method, using File.WriteAllText() and rebuilding the Lines with String.Join():

File.WriteAllText(destinationPath, String.Join(Environment.NewLine, lines), Encoding.UTF8)

String.Join() doesn't add the separator to the last element in the array.

▶ Using a StreamWriter, looping the lines in the array to the one before the last, then change the line terminator, setting the TextWriter.NewLine property to a null String (not a null Char):

Using stream As New StreamWriter(destinationPath, False, Encoding.UTF8)
    Dim index As Integer = 0
    For index = 0 To lines.Count - 2
        stream.WriteLine(lines(index))
    Next
    stream.NewLine = String.Empty
    ' index is set to the closure, lines.Count - 1
    stream.WriteLine(lines(index))
End Using

▶ With File.WriteAllLines() - which will add the NewLine chars to the last line - then use a FileStream to remove the trailing chars by setting the length of the File, calling FileStream.SetLength():

[Stream].Length = [Stream].Length - [Line terminator].Length`

Setting the Stream.Length to a lower value truncates the file.

File.WriteAllLines(destinationPath, lines, Encoding.UTF8)
Using fStream As New FileStream(destinationPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)
    fStream.SetLength(fStream.Length - Environment.NewLine.Length)
End Using

▶ Using a FileStream, to write the bytes returned by Encoding.UTF8.GetBytes(), adding a line terminator to all lines except the last one:

Using fStream As New FileStream(destinationPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)
    Dim lastLine = lines.Count - 1
    For index As Integer = 0 To lines.Count - 1
        Dim line As String = lines(index) & If(index <> lastLine, Environment.NewLine, "")
        Dim bytes = Encoding.UTF8.GetBytes(line)
        fStream.Write(bytes, 0, bytes.Length)
    Next
End Using

And many more...

As a note, you could simply ignore it, since when you read it back:

 lines = File.ReadAllLines(destinationPath, Encoding.UTF8).ToList()

You won't find an empty line in the collection. But, of course, this depends on the specific use-case (what these files are for).

Upvotes: 2

Related Questions