Эффективным способом написания в текстовом файле VB.NET
У нас есть некоторая информация, которую нам нужно написать (около 18 КБ).txt файл, хранящийся на одном из наших сетевых дисков. Файл переписывается примерно раз в 15 минут, но читается практически каждую секунду. В настоящее время мы используем StreamWriter для записи файла.
файловый сервер находится в удаленном месте, и пинг туда и обратно варьируется от менее 1 мс до 15 мс.
проблема в том, что иногда для записи содержимого требуется до шести секунд к файлу, который определенно слишком длинный даже после того, как мы рассмотрим скорость сети.
поэтому мне просто интересно, есть ли эффективный способ написать файл, используя VB.NET чтобы улучшить производительность? Java имеет очень хороший инструмент с именем BufferedOutputStream, который, к сожалению, недоступен в VB.NET (или я просто не нашел его).
7 ответов
самый быстрый вариант:
сначала соберите весь текст в одну большую строку, а затем используйте System.IO.File.WriteAllText(text)
.
эта функция была записана для чтения из базы данных и вывода в текстовый файл. Пожалуйста, не стесняйтесь использовать его в качестве отправной точки.
Sub MakeFile(ByVal Obj As Object)
Dim CountRow As Integer = 0
Dim TableName As String = CType(Obj, String())(0)
Dim CommandText As String = CType(Obj, String())(1)
Dim csvFileName As String = InitilizationSettings.DirectoryPath & TableName & ".txt"
If File.Exists(csvFileName) Then
File.Delete(csvFileName)
End If
Dim buffer() As Byte = {255}
Dim FileObject As New FileStream(csvFileName, FileMode.OpenOrCreate)
Dim MStream As New MemoryStream()
Dim StreamWriterObj As New StreamWriter(MStream)
Dim sb As New System.Text.StringBuilder
Dim x As Integer = 0
Dim reader As SqlDataReader
Dim cmd As New SqlCommand()
Dim conn As New SqlConnection(IOUtilities.GetConnectionString())
conn.Open()
With cmd
.CommandText = CommandText
.CommandTimeout = 1200
.CommandType = CommandType.Text
.Connection = conn
End With
reader = cmd.ExecuteReader()
Do While reader.Read()
'System.Console.Write("Loading rows to memory.../" & vbCr)
sb.Append(Chr(34))
sb.Append(reader.Item(0))
'System.Console.Write("Loading rows to memory...|" & vbCr)
sb.Append(Chr(34))
For i = 1 To reader.FieldCount - 1
sb.Append(",")
sb.Append(Chr(34))
sb.Append(reader.Item(i))
sb.Append(Chr(34))
Next
'System.Console.Write("Loading rows to memory...\" & vbCr)
sb.AppendLine()
'Write every 10000 rows of data to the file from the buffer
If x = 50000 Then
StreamWriterObj.Write(sb.ToString().ToCharArray())
MStream.Seek(0, SeekOrigin.Begin)
MStream.WriteTo(FileObject)
sb = New StringBuilder()
CountRow = CountRow + x
x = 0
End If
'System.Console.Write("Loading rows to memory...-" & vbCr)
x = x + 1
'LogEvents("Dumped " & strFileName & " to " & GetFilePath() & " at " & Now.ToString & vbCrLf & vbCrLf)
Loop
conn.Close()
reader.Close()
'Write any remaining data from the buffer to the file
StreamWriterObj.Write(sb.ToString().ToCharArray())
MStream.WriteTo(FileObject)
FileObject.Close()
System.Console.WriteLine(String.Format(vbCrLf & "Finished writing data to {1}", CountRow, csvFileName))
End Sub
рассмотрим их по очереди:
- создайте файл локально
- скопировать его в удаленную папку с временным расширением
- переименовать удаленный файл в исходное имя файла
Шаг 2 и 3 выглядит следующим образом (используя систему.IO):
string OriginalExtension = ".ok", TemporaryExtension = ".dat";
string tmpFileRemote = RemoteFile.Replace(TemporaryExtension, OriginalExtension);
File.Copy(fileName, RemoteFile, true);
File.Copy(RemoteFile, tmpFileRemote, true);
File.Delete(RemoteFile);
первый файл.Копирование занимает время. Но поскольку он не блокирует реальный файл, который люди используют, он не блокируется. второй файл.Copy фактически просто переименовывает файл и заменяет настоящий файл с только что загруженным. Файл.Удаляет временный файл загружен.
надеюсь, что это поможет.
есть несколько вещей, которые вступают в силу здесь. Но я обнаружил, что использование IO.Файл.AppendText функция значительно ускоряет процессы записи.
дополнительно, используя систему.Текст.Класс Stringbuilder в отличие от традиционной строки (предполагая, что вы объединяете текст для записи в файл) улучшает скорость еще больше.
посмотреть ускорение записи файла.
старая нить, но я думаю, что еще есть что добавить:
написать весь текст сразу, используя:
Система.ИО.Файл.WriteAllText (путь как строка, содержимое как строка).
однако для записи файла потребуется время, если он записывается через медленное соединение с удаленным местоположением. Чтобы пользователи не читали частично записанный файл, необходимо записать данные во временный файл на удаленном сервере. После того, как все данные были записаны, скопировать временный файл поверх старого файла, а затем удалите временный файл.
Если вы хотите быть действительно конечно, никто не читает частично написанный файл вы можете удалить старый файл, а затем переместить/переименовать временный файл, чтобы заменить файл, который вы только что удалили. В этом случае вы должны убедиться, что клиентские программы изящно обрабатывают файлы, не обнаруженные ошибки, которые неизбежно будут происходить время от времени.
Sub writefile()
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter("N:\GeneratedNumber.txt", False)
file.WriteLine("Player1 Skill is " & Skill(0))
file.WriteLine("Player1 Strength is " & Skill(1))
file.WriteLine("Player2 Skill is " & Skill(2))
file.WriteLine("Player2 Strength is " & Skill(3))
file.Close()
End Sub