Grosse Datei zeilenweise lesen und schreiben



  • Hallo,

    Eine sehr grosse Textdatei (mehrere hundert MB) soll zeilenweise eingelesen werden. Jede Zeile enthält drei Zahlen. Davon soll jeweils die dritte Zahl in eine neue Datei geschrieben werden. Die ersten beiden Zahlen werden nicht benötigt.

    Der Anfang der Input-Datei sieht im Texteditor so aus:

    -179.911067	  -85.007812	   -4.791818
     -179.733202	  -85.007812	   -4.934983
     -179.555336	  -85.007812	   -4.975407
     -179.377470	  -85.007812	   -5.033407
     -179.199605	  -85.007812	   -5.097786
     -179.021739	  -85.007812	   -5.152629
     -178.843874	  -85.007812	   -5.188445
     -178.666008	  -85.007812	   -5.227317
     -178.488142	  -85.007812	   -5.214427
    

    Das folgende Bild zeigt wie der Anfang der gleichen Datei im Hex-Editor aussieht:
    http://s7.directupload.net/file/d/3384/gzyf9fzi_gif.htm

    Ich habe folgenden Code geschrieben:

    openFileDialog1.ShowDialog();
                if (openFileDialog1.FileName != "")
                {
                    FileStream rStream = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
                    BinaryReader binReader = new BinaryReader(rStream);
                    FileStream wStream = new FileStream("test.txt",FileMode.OpenOrCreate, FileAccess.Write);
                    BinaryWriter binWriter = new BinaryWriter(wStream);
                    string a;
                    string[] b;
                    int n;
    
                    for (n = 0; n < 3; n++)
                    {
                        a = binReader.ReadString();
                        b = a.Split(Convert.ToChar(" "));
                        binWriter.Write(a + " <-- dies ist a \r\n");
                        binWriter.Write(b[2] + " <-- dies ist b[2] \r\n");
                    }
    
                    binReader.Close();
                    binWriter.Close();
                }
    

    Leider sieht das Ergebnis überhaupt nicht so aus wie erwartet:

    2-179.911067	  -85.007812	   -4.7 <-- dies ist a 
     -85.007812	 <-- dies ist b[2] 
    K1818
     -179.733202	  -85.007812	   -4.934983
     -179.555336	 <-- dies ist a 
     <-- dies ist b[2] 
    2 -85.007812	   -4.975407
     -179.3 <-- dies ist a 
     <-- dies ist b[2]
    

    Bitte gebt mir mal einen Denkanstoss was hier schiefläuft, oder wie man es besser machen könnte.

    Danke,
    Michael



  • Warum so kompliziert?

    Du hast jetzt nicht geschrieben in welchem Format die dritte Spalte an Zahlen geschrieben werden soll. Habe einfach mal eine Textdatei angenommen.

    static void Main(string[] args)
    {
    	using (TextWriter outp = File.CreateText(@"C:\out.txt"))
    	{
    		foreach (var line in File.ReadLines(@"C:\in.txt"))
    		{
    			var split = line.Split(new char[] { ' ' },  //Hier evtl. weitere Whitespace-Chars hinzufügen.
    					       StringSplitOptions.RemoveEmptyEntries);
    			outp.WriteLine(split[2]);
    		}
    	}
    
    	Console.ReadKey(true);
    }
    


  • Hallo,

    µ schrieb:

    Du hast jetzt nicht geschrieben in welchem Format die dritte Spalte an Zahlen geschrieben werden soll. Habe einfach mal eine Textdatei angenommen.

    Textdatei ist ok.

    In deinem Beispiel ist einiges an Syntax drin was ich so noch nie verwendet habe. Ich habe es einfach mal kopiert (ohne es im Detail zu verstehen) und stehe jetzt vor dem Problem dass es File.ReadLines() nicht gibt. Meintest du File.ReadAllLines() ?

    Gruß
    Michael



  • Nee ich meinte ReadLines. Gibt es erst ab NET-4.0. Programmierst Du noch mit VS 2008?

    ReadAllLines funktioniert, hat aber den Nachteil, die Datei auf einmal in den Speicher zu laden. Musst Du testen ob das bei Deiner großen Eingabedatei funktioniert, ansonsten:

    static void Main(string[] args)
    {
    	using (TextWriter outp = File.CreateText(@"C:\out.txt"))
    	{
    		using (TextReader inp = File.OpenText(@"C:\in.txt"))
    		{
    			string line;
    			while ((line = inp.ReadLine()) != null)
    			{
    				string[] split = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    				outp.WriteLine(split[2]);
    			}
    		}
    	}
    
    	Console.ReadKey(true);
    }
    

    Welche Syntax? Die using-Statements? Die geben nur, auf Exceptionsichere Weise, Resourcen durch Aufruf von Dispose am Ende frei: http://msdn.microsoft.com/en-us/library/yh598w02.aspx

    Edit: Das böse var ist auch rausgeflogen 😉



  • µ schrieb:

    Nee ich meinte ReadLines. Gibt es erst ab NET-4.0. Programmierst Du noch mit VS 2008?

    ReadAllLines funktioniert, hat aber den Nachteil, die Datei auf einmal in den Speicher zu laden. Musst Du testen ob das bei Deiner großen Eingabedatei funktioniert, ansonsten:

    ja, ich arbeite noch mit VS 2008. ReadAllLines hatte ich vorher schon probiert, scheitert aber daran dass die Input-Datei zu groß ist.
    Vielen Dank für deine Hilfe, jetzt läuft es!

    Gruß
    Michael



  • micha7 schrieb:

    ja, ich arbeite noch mit VS 2008. ReadAllLines hatte ich vorher schon probiert, scheitert aber daran dass die Input-Datei zu groß ist.

    Wenn Du nicht umsteigen kannst, ist es vielleicht nützlich einen Ersatz für File.ReadLines zu haben. Die Methode ist echt nützlich und lässt sich einfach nachbauen:

    class Program
    {
    	static IEnumerable<string> ReadLines(string path)
    	{
    		using (TextReader inp = File.OpenText(path))
    		{
    			string line;
    			while ((line = inp.ReadLine()) != null)
    				yield return line;
    		}
    	}
    
    	static void Main(string[] args)
    	{
    		foreach (string line in ReadLines(@"C:\trash\fu.txt"))
    			Console.WriteLine(line);
    
    		Console.ReadKey(true);
    	}
    }
    

Anmelden zum Antworten