【问题标题】:Efficient way of writing to a text file in VB.NET在 VB.NET 中写入文本文件的有效方法
【发布时间】:2011-01-24 19:37:21
【问题描述】:

我们需要将一些信息(大约 18 KB)写入存储在我们的一个网络驱动器上的 .txt 文件中。该文件大约每 15 分钟重写一次,但实际上至少每秒读取一次。我们目前正在使用 StreamWriter 写入文件。

文件服务器位于远程位置,往返 ping 的时间从不到 1 毫秒到 15 毫秒不等。

问题是,有时将内容写入文件需要长达六秒的时间,即使考虑到网络速度,这也肯定是太长了。

因此,我只是想知道是否有任何有效的方法来使用 VB.NET 编写文件以提高性能? Java 有一个非常好的工具,叫做 BufferedOutputStream,不幸的是,它在 VB.NET 中不可用(或者我只是没有找到它)。

【问题讨论】:

  • StreamWriter 已被缓冲。
  • 只是一个想法。如果您经常阅读它,您可能会遇到一些争用问题,多次读取会在短时间内锁定文件以防止写入,这会导致写入文件时偶尔出现延迟。
  • 网速是多少?正如 drventure 所描述的那样,争用可能是罪魁祸首。其他程序/用户是否使用了连接?

标签: vb.net file text io file-writing


【解决方案1】:

最快的选择:

先将所有文本收集到一个大字符串中,然后使用System.IO.File.WriteAllText(fileName, text)

【讨论】:

    【解决方案2】:

    编写此函数是为了从数据库中读取并输出到文本文件。请随意使用它作为起点。

     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
    

    【讨论】:

      【解决方案3】:

      依次考虑这些:

      1. 在本地创建文件
      2. 将其复制到带有临时扩展名的远程文件夹
      3. 将远程文件重命名为原始文件名

      第 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 删除上传的临时文件。

      希望对您有所帮助。

      【讨论】:

        【解决方案4】:

        这里有几件事生效。但是我发现使用 IO.File.AppendText 函数可以极大地加快编写过程。

        此外,使用 System.Text.Stringbuilder 类而不是传统字符串(假设您将文本连接到文件中)可以进一步提高速度。

        Speeding up File Writing

        【讨论】:

        • 嗯...看来这个 appendtext 听起来很有希望,非常感谢这篇文章,我会试一试告诉你,谢谢!
        【解决方案5】:

        一个旧线程,但我认为还有一些东西要补充:

        使用以下命令一次写入所有文本:
        System.IO.File.WriteAllText(路径为字符串,内容为字符串)。

        但是,如果文件是通过与远程位置的慢速连接写入的,则写入文件仍需要时间。为避免用户读取​​部分写入的文件,您应该将数据写入远程服务器上的临时文件。写入所有数据后,将临时文件复制到旧文件上,然后删除临时文件。

        如果你想真的确保没有人读取部分写入的文件,你可以删除旧文件,然后移动/重命名临时文件以替换刚刚删除的文件。在这种情况下,您必须确保客户端程序优雅地处理文件未找到错误,这些错误将不可避免地不时发生。

        【讨论】:

          【解决方案6】:

          考虑先写入本地驱动器,然后将该文件移动到网络驱动器。

          【讨论】:

            【解决方案7】:
            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
            

            【讨论】:

            • 如果您能解释您的答案如何比现有答案更有效(根据问题要求),那就太好了。另外,利用菜单中的“代码示例”突出显示代码。
            猜你喜欢
            • 2015-06-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-06
            • 2013-03-08
            • 2016-02-05
            • 1970-01-01
            • 2018-11-05
            相关资源
            最近更新 更多