vb.netのテキストファイルへの効率的な書き込み方法
-
24-10-2019 - |
質問
ネットワークドライブの1つに保存されている.txtファイルに書く必要がある情報(約18 kb)があります。ファイルは15分に1回約1回書き直されますが、少なくとも1秒ごとに読み取られます。現在、StreamWriterを使用してファイルを書き込んでいます。
ファイルサーバーは遠隔地にあり、往復pingは1ミリ秒から15ミリ秒未満まで変化します。
問題は、コンテンツをファイルに書き込むのに6秒もかかることがあります。これは、ネットワーク速度を考慮した後でも間違いなく長すぎます。
したがって、パフォーマンスを改善するためにVB.NETを使用してファイルを作成する効率的な方法があるかどうか疑問に思っていますか? Javaには、BufferedOutputStreamという名前の非常に優れたツールがありますが、残念ながらVB.NETでは利用できません(または私はそれを見つけていません)。
解決
最速のオプション:
最初にすべてのテキストを1つの大きな文字列に収集してから使用します 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は次のとおりです(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には時間がかかります。しかし、実際のファイルを使用している実際のファイルをロックしないため、ロックされません。 2番目のfile.copyは、実際にファイルを変更するだけで、実際のファイルをアップロードしたばかりのファイルに置き換えます。 file.deleteアップロードされた一時ファイルを削除します。
それが役立つことを願っています。
ここで実施されることがいくつかあります。しかし、私はそれを利用していることがわかりました io.file.appendtext 関数は書き込みプロセスを非常に高速化します。
さらに、System.text.StringBuilderクラスを使用して、従来の文字列とは対照的に(ファイルに書き込むためにテキストを付録すると仮定すると)、速度がさらに向上します。
古いスレッドですが、まだ追加するものがあると思います:
以下を使用して、すべてのテキストを一度に書きます。
system.io.file.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