2011-01-24 16 views
6

Abbiamo alcune informazioni che è necessario scrivere (circa 18   KB) in un file .txt memorizzato su una delle nostre unità di rete. Il file viene riscritto circa una volta ogni 15 minuti, ma viene letto praticamente almeno ogni secondo. Attualmente stiamo usando StreamWriter per scrivere il file.Modo efficiente di scrivere in un file di testo in VB.NET

Il file server si trova in una posizione remota e il ping di andata e ritorno varia da meno di 1   ms a 15   ms.

Il problema è che a volte bastano sei secondi per scrivere il contenuto nel file, che è decisamente troppo lungo anche dopo aver preso in considerazione la velocità della rete.

Pertanto, mi chiedo solo se esiste un modo efficace per scrivere il file utilizzando VB.NET per migliorare le prestazioni? Java ha un ottimo strumento chiamato BufferedOutputStream, che sfortunatamente non è disponibile in VB.NET (o semplicemente non l'ho trovato).

+1

StreamWriter è già memorizzato nel buffer. –

+0

Solo un pensiero. Se lo stai leggendo spesso, è possibile che tu stia riscontrando alcuni problemi di contesa, lettura multipla che blocca il file contro la scrittura per un breve periodo, causando il ritardo occasionale nella scrittura del file. – DarinH

+0

Qual è la velocità della rete? Di esso è basso, la contesa, come descritto da Drventure, potrebbe essere il culpetto. E la connessione utilizzata da altri programmi/utenti ?. – MarcelDevG

risposta

12

L'opzione più veloce:

Raccogliere tutti il ​​testo in una stringa di grandi dimensioni e poi usare System.IO.File.WriteAllText(text).

1

Ci sono un paio di cose che entrano in vigore qui. Ma ho scoperto che l'utilizzo della funzione IO.File.AppendText accelera enormemente i processi di scrittura.

Inoltre, l'utilizzo della classe System.Text.Stringbuilder a differenza di una stringa tradizionale (presupponendo che si concentri sul testo da scrivere in un file) migliora ulteriormente la velocità.

Vedere Speeding up File Writing.

+0

Mmm ... sembra che questo append testo sia davvero promettente, grazie mille per l'articolo, farò un tentativo e ti faccio sapere, grazie! – AZhu

1

Questa funzione è stata scritta per la lettura da un database e l'output in un file di testo. Sentiti libero di usarlo come punto di partenza.

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

non crei un'unità locale prima, per poi passare il file sul disco di rete.

1

considerare questi a loro volta:

  1. Creare il file in locale
  2. copiarlo nella cartella remota con una proroga temporanea
  3. Rinominare il file remoto al nome del file originale

Passo 2 e 3 è il seguente (utilizzando 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); 

Il primo File.Copy richiede tempo. Ma poiché non blocca il vero file che le persone stanno usando, non viene bloccato. Il secondo File.Copy in realtà semplicemente rinomina il file e sostituisce il file reale con quello appena caricato. File.Delete elimina il file temporaneo caricato.

Spero che questo aiuti.

-1
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

Sarebbe bello se potessi spiegare come la tua risposta è più efficiente (come domanda) rispetto alle risposte esistenti. Inoltre, utilizzare "Esempio di codice" nel menu per evidenziare il codice. – gsk

0

Un vecchio thread, ma penso che ci sia ancora qualcosa da aggiungere:

Scrivere tutto il testo in una sola volta utilizzando:
System.IO.File.WriteAllText (percorso come stringa, il contenuto come stringa).

Tuttavia, sarà necessario del tempo per scrivere il file se è stato scritto su una connessione lenta in una posizione remota. Per evitare che gli utenti leggano un file parzialmente scritto, è necessario scrivere i dati su un file temporaneo sul server remoto. Una volta che tutti i dati sono stati scritti, copiare il file temporaneo sul vecchio file e quindi eliminare il file temporaneo.

Se si desidera essere veramente sicuro che nessuno legge un file parzialmente scritto è possibile eliminare il vecchio file e quindi spostare/rinominare il file temporaneo per sostituire il file appena eliminato. In questo caso è necessario assicurarsi che i programmi client gestiscano con garbo gli errori di file non trovati che inevitabilmente si verificano di volta in volta.

Problemi correlati