2009-05-13 11 views
7

Ich habe eine Textdatei, in die geschrieben wird, als Teil eines sehr großen Datenextrakts. Die erste Zeile der Textdatei ist die Anzahl der extrahierten "Konten".Was ist der beste Weg, um Text in einer Datei mit C#/.NET zu ersetzen?

Aufgrund der Natur dieses Extrakts ist diese Zahl bis zum Ende des Prozesses nicht bekannt, aber die Datei kann groß sein (einige hundert MB).

Was ist der beste Weg in C#/.NET, um eine Datei (in diesem Fall eine einfache Textdatei) zu öffnen, und ersetzen Sie die Daten, die in der ersten "Zeile" des Textes ist?

WICHTIGER HINWEIS: - Ich muss keine "feste Menge an Bytes" ersetzen - das wäre einfach. Das Problem hierbei ist, dass die Daten, die am Anfang der Datei eingefügt werden müssen, variabel sind.

WICHTIGER HINWEIS 2: - Ein paar Leute haben gefragt/erwähnt, einfach die Daten im Speicher zu behalten und sie dann zu ersetzen ... aber das kommt überhaupt nicht in Frage. Der Grund, warum dieser Prozess aktualisiert wird, ist wegen der Tatsache, dass es manchmal beim Laden ein paar Gigs in den Speicher abstürzt.

+0

"##### \ r \ n" (bedeutet keine Auffüllung) "Sind Sie sicher, dass Sie keine führende Null haben können? –

Antwort

4

Wenn Sie können Sie einen Platzhalter einfügen, den Sie am Ende mit der tatsächlichen Zahl und Leerzeichen überschreiben.

Wenn das keine Option ist, schreiben Sie zuerst Ihre Daten in eine Cachedatei. Wenn Sie die tatsächliche Anzahl kennen, erstellen Sie die Ausgabedatei und hängen Sie die Daten aus dem Cache an.

+0

Ja, der einzige Weg, um das Schreiben der Daten zweimal zu vermeiden. Wenn es textbasiert ist, sollte es kein Problem geben, reservieren Sie einfach eine anständige Menge an Leerzeichen. –

+0

Dies ist, was ich * gerne * tun würde (reserviere etwas Leerstelle) - das einzige Problem ist, dass das Dateiformat, in das ich schreibe, exakt ##### \ r \ n (also kein Padding) benötigt. - Gute Antwort. –

+1

@Timothy: erlaubt es führende Nullen? –

1

Wenn die extrahierte Datei nur ein paar hundert Megabyte groß ist, können Sie den gesamten Text im Speicher behalten, bis die Extraktion abgeschlossen ist. Dann können Sie Ihre Ausgabedatei als letzte Operation schreiben, beginnend mit der Anzahl der Datensätze.

+3

"nur ein paar hundert Megabyte" ??? Sind Sie im Ernst ? – Cerebrus

+1

Ich habe nur 2 Gigs auf meiner Maschine - die meisten anderen in unserem Büro haben zwischen 4 und 8. Was ist 200MB. Vielleicht 10% des gesamten Speichers ... –

+0

Und was passiert in den Jahren, wenn die Datei "nur ein paar Gigabyte" ist, wirst du sie dann auch im Speicher behalten? –

2

Ich brauche keine "feste Menge an Bytes" zu ersetzen

Sind Sie sicher? Wenn Sie eine große Zahl in die erste Zeile der Datei schreiben (UInt32.MaxValue oder UInt64.MaxValue), können Sie die richtige Anzahl an Bytes durch die richtige Zahl ersetzen, aber mit Nullen aufgefüllt Es ist also immer noch eine gültige Ganzzahl. z.B.

Replace 999999 - your "large number placeholder" 
With  000100 - the actual number of accounts 
+0

Cleveres Workaround! - Aber die Dateispezifikation, mit der ich arbeite, wird das nicht akzeptieren ... aber sehr gute Gedanken :) –

+0

Stört es mich, zu fragen, warum nicht? –

+0

Es ist eine Dateispezifikation, es hat meine Frage nicht beantwortet: P –

3

BEST ist sehr subjektiv. Für jede kleine Datei können Sie einfach die gesamte Datei im Speicher öffnen und ersetzen, was Sie wollen, indem Sie eine Zeichenfolge ersetzen und dann die Datei neu schreiben.

Selbst für größere Dateien wäre es nicht so schwer in den Speicher zu laden. In den Tagen der Multi-Gigs des Gedächtnisses würde ich Hunderte von Megabyte in Betracht ziehen, um im Speicher noch leicht gemacht zu werden.

Haben Sie diesen naiven Ansatz getestet? Hast du ein echtes Problem damit gesehen?

Wenn dies eine wirklich große Datei (Gigabyte in Größe) ist, würde ich in Erwägung ziehen, alle Daten zuerst in eine temporäre Datei schreiben und dann die richtige Datei mit der Kopfzeile zuerst gehen und dann den Rest der Daten. Da es nur Text ist, würde ich wahrscheinlich nur Shell zu DOS aus:

TYPE temp.txt >> outfile.txt 
2

mir scheint, wenn ich die Frage richtig verstanden?

Was ist der beste Weg in C#/.NET, um eine Datei (in diesem Fall eine einfache Textdatei) zu öffnen, und ersetzen Sie die Daten, die in der ersten "Zeile" des Textes ist?

Wie wäre es, wenn Sie am Anfang der Datei ein Token {UserCount} platzieren, wenn es zum ersten Mal erstellt wird.

Verwenden Sie dann TextReader, um die Datei Zeile für Zeile zu lesen. Suchen Sie in der ersten Zeile nach {UserCount} und ersetzen Sie sie durch Ihren Wert. Schreiben Sie jede Zeile aus Sie lesen sich mit der Textwriter

Beispiel:

int lineNumber = 1; 
    int userCount = 1234; 
    string line = null; 

    using(TextReader tr = File.OpenText("OriginalFile")) 
    using(TextWriter tw = File.CreateText("ResultFile")) 
    { 

     while((line = tr.ReadLine()) != null) 
     { 
      if(lineNumber == 1) 
      { 
       line = line.Replace("{UserCount}", userCount.ToString()); 
      } 

      tw.WriteLine(line); 
      lineNumber++; 
     } 

    } 
+0

Das war im Wesentlichen, was ich tun musste, aber mein Ziel war es, * nicht * 2 Dateien erstellen zu müssen. –

+0

Ich habe eine weitere Lösung, die ich gesehen, aber noch nicht verifiziert oder ausprobiert habe. Im Grunde verwenden Sie etwas wie StreamWriter-Stream, um Ihre erste Datei zu schreiben und offen zu halten.Schreiben Sie auch, wie ich den Platzhalter vorgeschlagen habe und behalten Sie den Start- und Endpunkt des Tokens. Jetzt, wo du am Ende der Datei bist und du den UserCount hast, musst du einfach zurückgehen und das Token durch deinen Wert ersetzen. Um dies zu tun, verwenden Sie einen BitStream, von dem Sie glauben, dass Sie durch Zugriff auf StreamWriter.BaseStream darauf zugreifen können, und können Bytes an einen bestimmten Speicherort in Ihrem Stream schreiben. Werde es versuchen und es ausprobieren und posten. –

1

Ok, früher ich einen Ansatz vorgeschlagen, dass eine bessere, wenn Umgang mit bestehenden Dateien wäre.

In Ihrer Situation möchten Sie jedoch die Datei erstellen und während des Erstellungsprozesses zurück an den Anfang und schreiben Sie die Benutzeranzahl. Das wird genau das tun.

Hier ist eine Möglichkeit, die verhindert, dass Sie die temporäre Datei schreiben müssen.

private void WriteUsers() 
    { 
     string userCountString = null; 
     ASCIIEncoding enc = new ASCIIEncoding(); 
     byte[] userCountBytes = null; 
     int userCounter = 0; 

     using(StreamWriter sw = File.CreateText("myfile.txt")) 
     { 
      // Write a blank line and return 
      // Note this line will later contain our user count. 
      sw.WriteLine(); 

      // Write out the records and keep track of the count 
      for(int i = 1; i < 100; i++) 
      { 
       sw.WriteLine("User" + i); 
       userCounter++; 
      } 

      // Get the base stream and set the position to 0 
      sw.BaseStream.Position = 0; 

      userCountString = "User Count: " + userCounter; 

      userCountBytes = enc.GetBytes(userCountString); 

      sw.BaseStream.Write(userCountBytes, 0, userCountBytes.Length); 
     } 

    } 
+0

Dies ist natürlich die einzige Antwort auf die Anforderung, eine vorhandene Datei zu bearbeiten ... Danke! – ephraim

Verwandte Themen