patternMinor
Checking and updating lines in a file
Viewed 0 times
fileupdatingcheckingandlines
Problem
I am trying to check a bunch of files that should have a leading
I'm checking the first line which works and enters the update logic, which advances to the next row once I read the line in. So I added a writer.Write before I go into the
| delimiter but sometimes don't. If the first line doesn't have the |, the rest of the file won't, if it does have it, then the rest of the file will.I'm checking the first line which works and enters the update logic, which advances to the next row once I read the line in. So I added a writer.Write before I go into the
Do While loop and it works, but it seems like there would be a better way of doing this.Dim fileList As FileInfo() = dirList.GetFiles
For Each fiName In fileList
sFullName = fiName.FullName
sFileName = Path.GetFileNameWithoutExtension(fiName.ToString)
sDir = fiName.DirectoryName
Dim reader As New StreamReader(sFullName)
Dim line As String = reader.ReadLine()
If Not line.StartsWith("|") Then
Dim sNewFullName As String = sDir + "\" + sFileName + "_Temp.txt"
Dim writer As New StreamWriter(sNewFullName)
Dim sLine As String
sLine = "|" + line + System.Environment.NewLine
writer.Write(sLine)
Do While reader.Peek() <> -1
sLine = "|" + reader.ReadLine() + System.Environment.NewLine
writer.Write(sLine)
Loop
writer.Close()
reader.Close()
File.Delete(sFullName)
File.Move(sNewFullName, sFullName)
End If
reader.Close()
Next fiNameSolution
- Building filenames should be done using the
System.IO.Path.Combine()method. This ensures that you don't skip a "\" by accident and also enforces that no invalid path/file characters are used.
- Strings shouldn't be added to other strings (if done more than once), better use
System.Text.StringBuilder
As Mat's Mug already pointed out, your variable naming should be enhanced.
So
Dim sNewFullName As String = sDir + "\" + sFileName + "_Temp.txt"would become
Dim newFullName As String = System.IO.Path.Combine(currentDirectoryName, currentFileName + "_Temp.txt")As Mat's Mug also pointed out you need to extract some of the responsibilities to separate methods.
So let us introduce a method which takes a filename as input parameter and returns an array of Strings representing the content of the file.
Private Function GetFileContent(fileName As String) As String()
Return System.IO.File.ReadAllLines(fileName)
End Functionnext we introduce a function which takes a filename as input parameter and returns wether the first character of the first line is the "|" . We first check if the read line is maybe
Nothing by using String.IsNullOrWhiteSpace(). This prevents an exception if the file would be empty. Private Function FirstLineStartsWithPrefix(fileName As String, prefix As String) As Boolean
Using reader As New System.IO.StringReader(fileName)
Dim line As String = reader.ReadLine()
Return Not String.IsNullOrWhiteSpace(line) AndAlso line.StartsWith(prefix)
End Using
End FunctionNext we introduce a method which takes a String array as input parameter and returns the prefixed content. We are using the
Append() and AppendLine() method. Both methods are returning a StringBuilder object, so we can use it in a fluent way. Private Function AddPrefixToLines(content As String(), prefix As String) As String
Dim sb As New System.Text.StringBuilder(1024)
For Each line As String In content
sb.Append(prefix).AppendLine(line)
Next
Return sb.ToString()
End FunctionNext we introduce a method which takes a FileInfo object as input parameter and returns nothing (a Sub).
Private Const pipePrefix As String = "|"
Private Const fileNamePostFix As String = "_Temp.txt"
Private Sub ProcessFile(currentFileInfo As FileInfo)
Dim fullName As String = currentFileInfo.FullName
If Not FirstLineStartsWithPrefix(fullName, pipePrefix) Then Exit Sub
Dim fileContent As String() = GetFileContent(currentFileInfo.FullName)
Dim prefixedContent As String = AddPrefixToLines(fileContent, pipePrefix)
Dim pureFileName As String = Path.GetFileNameWithoutExtension(fullName)
Dim newFileName As String = Path.Combine(currentFileInfo.DirectoryName, pureFileName & fileNamePostFix)
File.WriteAllText(newFileName, prefixedContent)
currentFileInfo.Delete()
File.Move(newFileName, fullName)
End SubNow your initial code will look like
Dim fileList As FileInfo() = dirList.GetFiles
For Each fiName In fileList
ProcessFile fiName
NextCode Snippets
Dim sNewFullName As String = sDir + "\" + sFileName + "_Temp.txt"Dim newFullName As String = System.IO.Path.Combine(currentDirectoryName, currentFileName + "_Temp.txt")Private Function GetFileContent(fileName As String) As String()
Return System.IO.File.ReadAllLines(fileName)
End FunctionPrivate Function FirstLineStartsWithPrefix(fileName As String, prefix As String) As Boolean
Using reader As New System.IO.StringReader(fileName)
Dim line As String = reader.ReadLine()
Return Not String.IsNullOrWhiteSpace(line) AndAlso line.StartsWith(prefix)
End Using
End FunctionPrivate Function AddPrefixToLines(content As String(), prefix As String) As String
Dim sb As New System.Text.StringBuilder(1024)
For Each line As String In content
sb.Append(prefix).AppendLine(line)
Next
Return sb.ToString()
End FunctionContext
StackExchange Code Review Q#68427, answer score: 5
Revisions (0)
No revisions yet.