Announcement

Collapse
No announcement yet.

Anfängerfrage: Werte aus File berechnen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Anfängerfrage: Werte aus File berechnen

    hallo liebes entwickler forum.

    ich beschäftige mich seit ein paar wochen mit c# und hänge da nun an einem kleinen problem

    ich möchte ein txt file einlesen mit werten und diese stehen in untersciedlichen spalten, getrennt durch ein tabulator.

    das file hat die form:

    1 2 3
    4 5 6

    usw...

    nun möchte ich z.b. nur das alle werte in der 3. spalte addiert werdern (also 3 und 6) oder das min und max bestimmen oder den mittelwert. (wie die formeln dafür lauten weiss ich)

    nun habe ich soweit folgendes geschrieben:

    Code:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    
    namespace DatLesen
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Alle Zeilen in einem Rutsch einlesen
                string[] zeilen = File.ReadAllLines("c:\\test.txt");
    
                //Alle Zeilen in einer Schleife durchlaufen
                foreach (string zeile in zeilen)
                {
                    //zeile aufteilen
                    string[] aufgeteilt = zeile.Split('\t');
    
                    //Ausgeben
                    Console.WriteLine(aufgeteilt[0] + "\t" + aufgeteilt[1] + "\t" + aufgeteilt[2]);
                
                
                }
                
                Console.ReadLine();
            }
        }
    }
    das funktioniert soweit wunderbar.
    nun möchte ich wie schon erwähnt alle werte der letzten spalte "anfassen" also das
    Code:
    aufgeteilt[2]
    jedoch weiss ich nicht wie ich das angehen soll ich stehe da irgendwie auf dem schlauch. versuche ich das über eine schleife mit mit der gesamlänge dann gibts nur fehler und funktioniert nicht

    ich weiss das ist eine total simple sache aber ich weiss halt nicht wie ich das angehen soll um diese einzige spalte jetzt auf zu summieren im sinne von:

    sum += aufgeteilt[2];

    könnt ihr mir da weiter helfen ?

  • #2
    Hallo

    So auf die Schnell könnte man die Daten wie in einer Matrix (zweidimensionales Array) aufteilen:
    0 1 2 3
    1
    2
    3
    4
    5
    usw...

    Am Ende bearbeitet man die Zahlen an der Position [1 bis x][2]
    MfG
    Cheat-Sheets for Developers / Programming Quotes

    Comment


    • #3
      Deine textuelle Beschreibung was du zur Berechnung tun kannst hört sich erstmal sinnvoll an. Wenn du also doch Fehler bekommst zeig uns den Code dazu und/oder nenn uns die Fehlermeldungen die du bekommst dann kann man dir helfen.

      Achja sollte braindead2000 == acid2000 sein, so wäre es vielleicht hilfreich deine Daten in einem Datenbankformat zu exportieren. Dort bekommst du dann per SQL Zugriff auf Statistikfunktionen(also min,max,sum,avg und Konsorten) die dir sicher weiterhelfen.

      Comment


      • #4
        Wenn Du fertige Statistikfunktionen nutzen willst, empfehle ich mal ein Blick auf List<T>. Dort ist schon alles dabei.
        z.B.:
        Code:
        // als List-Variante
        List<int> lInteger = new List<int>() { 1, 2, 3, 4 };
        int iMin = lInteger.Min();
        double dAvg = lInteger.Average();
        Alternativ kannst Du auch einen Array von Integer (oder alles, was IEnumerable<T> implementiert) wählen, aber im Normalfall ist eine Liste zu bevorzugen...

        Code:
        // ... oder als Array-Variante
        int[] ints = { 1, 2, 3, 4 };
        int iMin = ints.Min();
        double dAvg = ints.Average();
        HTH,
        Karsten

        P.S.: Achja, das ganze funktioniert aber erst ab C# 3.0...
        Zuletzt editiert von Rumtata; 03.04.2008, 13:07. Reason: Post scriptum

        Comment


        • #5
          @markus lahr

          wenn ich die datei einlese und z.b. mir nur die
          Code:
          aufgeteilt[2]
          ausgeben lass, dann bekomm ich ja genau nur die 3,6,9 usw also genau die letzte spalte. und z.b. mit der will ich dann auch nur rechnen. das muss doch gehen auch die nur irgendwie auf zu summieren oder ähnliches ?

          @ralf jansen

          ich weiss nicht genau wie das geht mit der datanbank in c# alle tutorials die ich bis jetzt gelesen hab verweisen dabei immer auf den MS SQL Server. nur in einer datenbank möchte ich es nicht. es sollen ja auch noch statistische auswertungen getroffen werden wie standartabweichung usw über einen algorithmus.

          Code:
          using System;
          using System.Collections.Generic;
          using System.Text;
          using System.IO;
          
          namespace DatLesen
          {
              class Program
              {
                  static void Main(string[] args)
                  {
                      //Alle Zeilen in einem Rutsch einlesen
                      string[] zeilen = File.ReadAllLines("d:\\praktikum\\pts_ring.txt");
          
                      //Alle Zeilen in einer Schleife durchlaufen
                      foreach (string zeile in zeilen)
                      {
                          //zeile aufteilen
                          string[] aufgeteilt = zeile.Split('\t');
          
                          //Ausgeben
                          Console.WriteLine(/*aufgeteilt[0] + "\t" + aufgeteilt[1] + "\t" +*/ aufgeteilt[2]);
                                      
                      }
          
                      double avg = 0;
                      for (int i = 0; i < 10; i++)
                          avg = avg + aufgeteilt[2];
                      avg = avg / 10;
                      Console.WriteLine("Durchschnitt: " + avg);
           
                      Console.ReadLine();
                  }
              }
          }
          bei dem fettgedrucken kommt halt die aussagen das "'aufgeteilt' nicht im aktuellen kontext auftaucht" ein weiterer fehler ist auch das ich ja einen string einlese aber mit double rechnen möchte und ich es also umwandeln muss.

          das einzige was ich kenne beim umwandeln ist sowas:

          Code:
          double deg = Convert.ToDouble(Console.ReadLine());
          aber ich weiss halt nicht wie ich es noch anders umwandeln kann wie in meinem fall

          ich weiss nicht weiter in dem sinne

          Comment


          • #6
            Hallo braindead2000,

            Datenbank ist nicht gleich MS-SQL-Server! Es gibt noch viele andere "echten" Datenbanken, dazu Access als "halbe" DB und z.B. csv-Textdateien als DB-ähnliche Daten.

            Das ist bei Dir wirklich die Lösung: Deine Datei enthält mehrere Zeilen; jede Zeile ist gleich aufgebaut; in jeder Spalte stehen eigentlich Zahlen. Du willst die Spalten auswerten. Also ist es natürlich sinnvoll, die Textdatei in ein Array aus Zeilen und Spalten unter Berücksichtigung der Datentypen einzulesen. Die passende Klasse im Arbeitsspeicher ist eine DataTable.

            Also schau Dir zunächst das Thema C# Ausreißer aus Punktwolke elimenieren an; dort habe ich als Variante 3 das Einlesen einer csv-Textdatei in eine DataTable skizziert.

            Zum Einarbeiten in das Verwenden von Datenbanken ist das OpenBook Visual C# Kap.26 geeignet. Wenn Du Sql-Klassen durch OleDb-Klassen ersetzt und einen passenden ConnectionString wählst, kannst Du die Erläuterungen auch auf eine csv-Datei übertragen.

            Außerdem fehlen Dir anscheinend noch einige Grundlagen. Unter C# und NET überhaupt musst Du genau auf die verwendeten Datentypen achten. In einer Textdatei stehen Texte und keine Zahlen; wenn Du Methoden (Funktionen) für Zahlen verwenden willst, benötigst Du also vorher Konvertierungen. Alle Variablen haben einen bestimmten Geltungsbereich, z.B. innerhalb eines Blockes {}. Zur allgemeinen Einarbeitung siehe z.B. auch das OpenBook C#.

            Noch ein paar Hinweise dazu: "aufgeteilt[2]" ist ein Teil eines String-Arrays, kann also natürlich als Text angezeigt werden. Texte können natürlich nicht summiert werden; vor dem Rechnen benötigst Du etwas wie Int32.TryParse (bitte benutze von Anfang an nicht die Convert-Klasse, die ist nicht so günstig).

            Bei Deinem Versuch der Durchschnittsberechnung: Bedenke doch, was an dieser Stelle unter "aufgeteilt" verstanden werden könnte. Wie soll das denn funktionieren...

            Du glaubst, Du kommst nicht weiter? Du musst doch nur den Code ein wenig umstellen und das Umsetzen von Strings in Zahlen einbauen (und ein Durchschnitt auf genau 10 Zahlen ist natürlich Quatsch, aber das weißt Du wahrscheinlich selbst).

            Jürgen

            Comment


            • #7
              Die Aufgeteilt Variable mußt du aus dem foreach Block rausziehen sonst ist sie auch nur in diesem Block bekannt.

              Code:
                          //Alle Zeilen in einer Schleife durchlaufen
                          string[] aufgeteilt;
                          foreach (string zeile in zeilen)
                          {
                              //zeile aufteilen
                              aufgeteilt = zeile.Split('\t');
              ...
              Konvertieren string-> double kannst du z.B. folgendermaßen
              Wobei du noch die Einstellungen von NumberFormatInfo (Dezimaltrenner etc.)
              noch den wirklichen Gegebenheiten deines Strings aus der Datei anpassen mußt.

              Code:
                                  NumberFormatInfo numberFormatInfo = new NumberFormatInfo( );
                                  numberFormatInfo.NumberDecimalSeparator = ",";
                                  numberFormatInfo.NumberGroupSeparator = ".";
                                  double.Parse(aufgeteilt[2], numberFormatInfo);

              Comment


              • #8
                danke ich werde es mir mal zu gemüte führen und testen.
                das eigentliche problem ist meist nur die umsetzung, da es theoretisch ansich klar ist. nur es hapert an der umsetzung und meist dem verständnis am programmieren
                für mich ist es schwer sich da ein zu fuchsen. einfache sachen sind nicht das ding aber manchmal fehlt mir die logik. danke für eure tipp!!

                Comment


                • #9
                  so ich habe nun mal versucht eine connection zusammen zu basteln. jedoch meckert er über die "\"
                  Code:
                  using System;
                  using System.Collections.Generic;
                  using System.Text;
                  using System.Data;
                  using System.Data.OleDb;
                  
                  namespace OleDB
                  {
                      class Program
                      {
                          public static void Main()
                          {
                          string source = Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\test\pts_ring.txt\;Extended Properties="text;HDR=Yes;FMT=Delimited";
                          string command="SELECT * FROM pts_ring.txt";
                          OleDbCommand mCommand = new OleDbCommand(); 
                          OleDbConnection mConnection=new OleDbConnection(source);
                          mConnection.Open();
                          mCommand.ActiveConnection=mConnection; 
                          mCommand.CommandText=command;
                          OleDbDataReader mReader;
                          mCommand.Execute(out mReader); 
                          
                          while (mReader.Read()) 
                              { 
                              Console.WriteLine(mReader.GetString(0) + ":" + mReader.GetInt32(1));
                              }
                           
                          mReader.Close();
                          
                          mConnection.Close(); 
                          }
                      }
                  }
                  als fehler kommt immer folgendes:

                  Code:
                  Program.cs(13,95): error CS1056: Unexpected character '\'
                  ich habe mich aber an den beispielen des openboocks gehalten, verstehe aber nicht warum nun dieses zeichen da nciht stimmt. habe es auch mit "\\" versucht aber gleiches problem.

                  desweiteren ist mir auch nicht ganz klar wie ich da mit dem DataTable arbeiten soll (ich versteh es einfach nicht )
                  vorallem nicht über die console. bei dem grafischen ist es mir noch klarer, weil ich da eher sehe was passiert. aber ich möchte es so auch hinbekommen

                  Comment


                  • #10
                    Hallo,

                    der Fehler steckt offensichtlich im ConnectionString. Am Anfang fehlen die Gänsefüßchen. Innerhalb eines Strings werden durch '\' Spezialzeichen gekennzeichnet; der Backslash muss verdoppelt werden. Ebenso müssen Gänsefüßchen, die zu einem String gehören, durch "\"" ersetzt werden. (Alternativ kann ein String mit '@' gekennzeichnet werden; dann kann auf die Escape-Zeichen verzichtet werden. Das empfiehlt sich immer dann, wenn viele Verzeichnisnamen vorkommen.) Das gehört zu den Grundlagen von C#, siehe mein Hinweis auf die OpenBooks.

                    Dein Hauptfehler dürfte sein (ich habe jetzt nicht gezählt, wo das 95. Zeichen steht), dass hinter dem Dateinamen noch ein Backslash kommt. Der wäre mit Sicherheit falsch.

                    In einem anderen Forum habe ich den Hinweis gelesen, dass im ConnectionString nur das Verzeichnis genannt werden sollte und der Dateiname nur im Select-Befehl steht.

                    Die Lösung mit DataTable würde es wirklich einfacher machen, etwa so:
                    Code:
                    DataTable table = new DataTable("pts_ring");
                    table.Columns.Add("Zahl1", typeof(double));
                    table.Columns.Add("Zahl2", typeof(double));
                    table.Columns.Add("Zahl3", typeof(double));
                    using(OleDbConnection conn = new OleDbConnection(source)) {
                        OleDbCommand cmd = new OleDbCommand(command);
                        OleDbDataAdapter da = new OleDbDataAdapter();
                        da.SelectCommand = cmd;
                        da.Connection = conn;
                        da.Fill(table);
                    }
                    Der letzte Befehl liest die Daten direkt in die DataTable ein.

                    Bitte gewöhne Dir an, dass DbConnection immer in einem using-Block gekapselt wird und alles, was nur dafür benötigt wird, in diesen Block gesetzt wird.

                    Jürgen

                    Comment


                    • #11
                      danke für die hilfe ich werde es morgen auf arbeit gleich weiter versuchen und hoffe auf ein ergebnis. dickes *THUMBS UP* für die hilfe hier im forum

                      EDIT://
                      Zuletzt editiert von braindead2000; 04.04.2008, 09:09.

                      Comment


                      • #12
                        hallo,

                        ich habe das jetzt mal so versucht:
                        Code:
                        using System;
                        using System.Collections.Generic;
                        using System.Text;
                        using System.Data;
                        using System.Data.OleDb;
                        
                        namespace DataTab
                        {
                            class Program
                            {
                                static void Main(string[] args)
                                {
                                    string source = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\test\\pts_ring.txt\\" + 
                                                    @";Extended Properties=""text;HDR=Yes;FMT=TabDelimited\""";
                                    string SelectAnweisung = "SELECT * FROM pts_ring.txt";
                                    DataTable table = new DataTable("pts_ring");
                                    table.Columns.Add("Zahl1", typeof(double));
                                    table.Columns.Add("Zahl2", typeof(double));
                                    table.Columns.Add("Zahl3", typeof(double));
                                    using (OleDbConnection conn = new OleDbConnection(source))
                                    {
                                        OleDbCommand cmdSelect = new OleDbCommand(SelectAnweisung);
                                        OleDbDataAdapter da = new OleDbDataAdapter();
                                        da.SelectCommand = cmdSelect;
                                        da.Connection = conn;
                                        da.Fill(table);
                                    }
                                }
                            }
                        }
                        mein problem ist das er mit Connection nichts anfangen kann
                        Code:
                        'System.Data.OleDb.OleDbDataAdapter' does not contain a definition for 'Connection'
                        desweiteren habe ich immer noch keine idee wie ich die 3. spalte dann "anfassen" kann um mit ihr zu rechnen. z.b. einfach auf zu summieren in der art von
                        Code:
                        sum += Daten aus spalte 3
                        zieht er sich die ROWs eigentlich dann allein rein und kann ich mir das auf der console dann auch anzeigen lassen ? (auch wenn es lange dauert, nur erstmal um zu sehen das er es liest)

                        mfg
                        Zuletzt editiert von braindead2000; 04.04.2008, 09:29.

                        Comment


                        • #13
                          Fehler mit da.Connection:
                          Das war eine Falle von mir. Ich habe aus dem Kopf die Befehle hingeschrieben. Wichtig ist, dass DbDataAdapter und DbCommand zusammengehören und über die DbConnection verarbeitet werden sollen. Also müssen diese drei Objekte auf jeden Fall verknüpft werden. Dazu gibt es viele Möglichkeiten: DbCommand hat die Connection-Eigenschaft, der DbDataAdapter aber nicht. Andererseits gibt es für beide Klassen einen Konstruktor mit Connection; also kann man auch schreiben:
                          Code:
                                      using (OleDbConnection conn = new OleDbConnection(source))
                                      {
                                          OleDbDataAdapter da = new OleDbDataAdapter(SelectAnweisung, conn);
                                          da.Fill(table);
                                      }
                          Also verlasse Dich nicht darauf, dass alles im Forum vollständig und korrekt ist. Dazu hast Du die SDK-Doku, um solche Zusatzinformationen selbst zu holen.

                          Zur Auswertung der Daten
                          Dazu habe ich mich bisher in der Tat bedeckt gehalten. Es gibt vor allem zwei Möglichkeiten:

                          1. Jede Zeile wird in einer Schleife untersucht. Wie Du auf einen einzelnen Wert zugreifen kannst, wird in der SDK-Doku unter DataRow.Item-Eigenschaft erläutert. Da Deine Tabelle nur double-Werte enthält (hoffentlich), geht es so:
                          Code:
                          foreach(DataRow row in table.Rows) {
                              double value0 = (double)row[0];   //  für die 0-te Spalte
                              double value2 = (double)row["Zahl3"];   //  für diese Spalte
                              //  mit diesen Werten kannst Du innerhalb der Schleife arbeiten
                          }
                          2. Es gibt auch direkte Berechnungen, siehe DataTable.Compute-Methode:
                          Code:
                          double sum = table.Compute("Sum(Zahl3)", "Zahl3 >= 0");
                          Du solltest an meinen Hinweisen auch erkennen: Die SDK-Doku ist das wichtigste Hilfsmittel, wichtiger als alle Foren!

                          Jürgen

                          Comment


                          • #14
                            ok danke!!
                            das habe ich alles soweit verstanden. aber ein problem habe ich trotzdem noch

                            ich habe es nun soweit angepasst, jedoch nun ist der pfad nichtmehr zulässig ?
                            Code:
                            'C:\\test\\pts_ring.txt' ist kein zulässiger Pfad. Stellen Sie sicher, dass der Pfad richtig eingegeben wurde und dass Sie mit dem Server, auf dem sich die Datei befindet, verbunden sind.
                            ohje ich verzweifle dadran noch. hab es doch so umgesetzt...

                            Code:
                            string source = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test\\pts_ring.txt" + 
                                                        @";Extended Properties=""text;HDR=Yes;FMT=TabDelimited\""";
                                        string SelectAnweisung = "SELECT * FROM pts_ring.txt";
                                        DataTable table = new DataTable("pts_ring");
                                        table.Columns.Add("Zahl1", typeof(double));
                                        table.Columns.Add("Zahl2", typeof(double));
                                        table.Columns.Add("Zahl3", typeof(double));
                                        using (OleDbConnection conn = new OleDbConnection(source))
                                        {
                                            
                                            OleDbDataAdapter da = new OleDbDataAdapter(SelectAnweisung,conn);
                                            da.Fill(table);

                            Comment


                            • #15
                              Der @ vor einem String sagt, dass der Inhalt "echt" gemeint ist, also ein '\' wirklich ein Backslash ist und kein Escape-Zeichen. Die Fehlermeldung weist ja auch auf die doppelten "\\" hin. Also: Wenn '@' vor einem String, dann '\' normal verwenden.

                              Wenn Du die vielen Parameter mit und ohne Gänsefüßchen vermeiden willst, dann benutze doch DbConnectionStringBuilder, da kannst Du die Bestandteile einzeln registrieren und bekommst am Schluss den Gesamtstring.

                              Jürgen

                              Comment

                              Working...
                              X