Эффективный способ записи в текстовый файл в VB.NET - PullRequest
7 голосов
/ 24 января 2011

У нас есть некоторая информация, которую нам нужно записать (около 18 КБ) в файл .txt, хранящийся на одном из наших сетевых дисков. Файл перезаписывается примерно раз в 15 минут, но читается практически каждую секунду. В настоящее время мы используем StreamWriter для записи файла.

Файловый сервер находится в удаленном месте, и пинг туда и обратно варьируется от менее 1 мс до 15 мс.

Проблема в том, что иногда для записи содержимого в файл может потребоваться до шести секунд, что, безусловно, слишком долго, даже после того, как мы учитываем скорость сети.

Поэтому мне просто интересно, есть ли эффективный способ записи файла с использованием VB.NET для повышения производительности? В Java есть очень хороший инструмент с именем BufferedOutputStream, который, к сожалению, недоступен в VB.NET (или я просто не нашел его).

Ответы [ 7 ]

13 голосов
/ 24 января 2011

Самый быстрый вариант:

Сначала соберите весь текст в одну большую строку, а затем используйте System.IO.File.WriteAllText(text).

1 голос
/ 29 июля 2011

Рассмотрим их по очереди:

  1. Создайте файл локально
  2. Скопируйте его в удаленную папку с временным расширением
  3. Переименуйте удаленный файл в исходный файлname

Шаг 2 и 3 выглядит следующим образом (с использованием System.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);

Первый File.Copy занимает время.Но поскольку он не блокирует реальные файлы, которые используют люди, он не блокируется.Второй File.Copy фактически просто переименовывает файл и заменяет реальный файл только что загруженным.File.Delete удаляет временный загруженный файл.

Надеюсь, это поможет.

1 голос
/ 24 января 2011

Эта функция была написана для чтения из базы данных и вывода в текстовый файл.Пожалуйста, не стесняйтесь использовать его в качестве отправной точки.

 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
1 голос
/ 24 января 2011

Есть несколько вещей, которые вступают в силу здесь.Но я обнаружил, что использование функции IO.File.AppendText значительно ускоряет процессы записи.

Кроме того, использование класса System.Text.Stringbuilder в отличие от традиционной строки (при условии, что вы пишете текст для записи в файл), скорость еще больше увеличивается.

См. Ускорение записи в файл .

0 голосов
/ 04 ноября 2017

Старая ветка, но я думаю, что еще есть что добавить:

Записать весь текст сразу, используя:
System.IO.File.WriteAllText (путь как строка, содержимое как строка).

Однако для записи файла все равно потребуется время, если он записывается по медленному соединению с удаленным местоположением.Чтобы пользователи не читали частично записанный файл, вы должны записать данные во временный файл на удаленном сервере.Как только все данные будут записаны, скопируйте временный файл поверх старого файла и затем удалите временный файл.

Если вы хотите быть действительно , убедитесь, что никто не читает частично записанный вами файл.Можно удалить старый файл, а затем переместить / переименовать временный файл, чтобы заменить только что удаленный файл.В этом случае вы должны убедиться, что клиентские программы корректно обрабатывают ошибки, связанные с отсутствием файлов, которые неизбежно будут происходить время от времени.

0 голосов
/ 03 ноября 2014
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
0 голосов
/ 25 января 2011

Попробуйте сначала записать на локальный диск, а затем переместить этот файл на сетевой диск.

...