Announcement

Collapse
No announcement yet.

Einlesen und Zwischenspeichern von Textdateien

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

  • Einlesen und Zwischenspeichern von Textdateien

    Hallo Leute,

    bei meinem Problem handelt es sich um folgende Aufgabe:
    "Die Klasse FileCache dient zum Einlesen und Zwischenspeichern von Dateien. Erstellen Sie in der Klasse FileCache eine statische Methode ReadLine.

    Der Methode ReadLine wird der Dateipfad zu einer Textdatei übergeben. Diese Textdatei wird von der Methode eingelesen und jede einzelne Zeile über einen Enumerator zurückgegeben.

    Die Zeilen der zuletzt eingelesenen Datei sollen zusätzlich in einer Liste zwischengespeichert werden, so dass bei einem nochmaligen Aufruf der Methode ReadLine diese nicht noch einmal eingelesen werden muss."

    Irgendwie komme ich mit der Aufgabe nicht wirklich zurecht und mein Ansatz sieht sehr dürftig aus:
    [highlight=c#]using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;

    namespace My.Collections
    {
    public class FileCache
    {
    public static IEnumerator ReadLine(Path path)
    {
    List<string> lines = new List<string>();
    StreamReader reader = new StreamReader(path.ToString());
    lines.Add(reader.ReadLine());
    yield return lines[lines.Count - 1];
    }
    }
    }
    [/highlight]

    Habt ihr vielleicht einen besseren Ansatz, Hinweise oder Vorschläge für mich? Den letzten Teil der Aufgabe habe ich irgendwie nicht ganz begriffen:
    Die Zeilen der zuletzt eingelesenen Datei sollen zusätzlich in einer Liste zwischengespeichert werden, so dass bei einem nochmaligen Aufruf der Methode ReadLine diese nicht noch einmal eingelesen werden muss.

    Ich zweifel auch besonders an meiner Lösung, da mein Lösungsweg so knapp ist, und die Aufgabe doppelt so viele Punkte geben soll, wie die anderen.

    Lieben Gruß
    Zuletzt editiert von kogen; 24.05.2015, 19:33.

  • #2
    List lines = new List();
    nicht in der Methode definieren, sondern als statische Membervariable.
    Somit steht dann das Ergebnis des letzten einlesens solange zur Verfügung, bis ein neues einlesen erfolgt. I

    In der Methode ReadLine muss dann natürlich diese Liste als erstes geleert werden, sonst werden alle Dateien rangehangen
    Zuletzt editiert von Christian Marquardt; 24.05.2015, 20:20.
    Christian

    Comment


    • #3
      Du hast aber aus dem vollen gegriffen oder? Da ist mal in jedes Features von dir reingegriffen worden, sinnlos durchmischt, und eindeutig wenig verstanden worden. Zu deiner Entschuldigung ist die Aufgabe auch mal selten dämlich gestellt und ich gehe davon aus das derjenige der die gestellt hat genauso verwirrt wie dein Lösungsansatz ist Oder du hast Infos weggelassen die hilfreich wären das zu verstehen, z.B. das ihr gerade das Theme IEnumerable + yield durchnehmt, und das wieder ein klassisches Beispiel für eine Aufgabe ist die man mit anderen Mitteln als die in dessen Kontext sie gestellt wurde und die zum lösen benutzt werden sollen besser lösen kann.

      Ich zähle mal auf was ich an deinem Code sehe

      a.) Path ist eine Klasse die Pathes verarbeiten kann (sauber zerlegen, zusammensetzen etc.) aber keinen darstellt. Ein path ist einfach ein string also übergib an die Methode einfach einen string. Nebenbei Path ist auch eine statische Klasse es ist sinn frei die über Parameter rum zureichen.
      b.) IEnumerator stellt nichts aufzählbares dar. Derjenige der aufzählt ist ein IEnumerator. Etwas aufzählbares wäre ein IEnumerable (also ein Array, eine List<T>, eine Collection etc.)
      c.) yield return stellt ein Element von etwas aufzählbarem dar (IEnumerable) pass also gar nicht zu deinem Rückgabetyp vom Typ IEnumerator.
      d.) da du nur einmal yield return aufrufst kämme (wenn es den funktionieren würde) auch maximal 1 Element zurück. Sinn macht yield return innerhalb einer Schleife oder wenn man tatsächlich immer nur eine Liste von 0 oder 1 Element zurückgeben will.

      Zur Aufgabe da steht und jede einzelne Zeile über einen Enumerator zurückgegeben. Das würde ich mal so interpretieren das die Methode einen Enumerator verwenden soll aber nicht das sie einen zurückgeben soll. Ein simpler foreach ist schon ein Enumerator/Iterator aber auch jeder andere Schleifenkonstrukt.
      Die Aufgabe wird an dieser Stelle unsinnig da man alle Zeilen cachen soll und es Methoden (im Framework) die das ganze File als Stringliste einlesen wird der Hinweis mit dem Enumerator.

      Ich zeige mal eine Version ohne Enumerator (bzw. eigentlich mit den in File.ReadAllLines steckt natürlich letztlich auch etwas drin das man Enumerator nennen könnte) . Um der Aufgabenstellung zu entsprechen müßtest du File.ReadAllLines noch durch einen eigenen Enumerator ersetzen. Zum Beispiel wie du schon gezeigt hast mit einem StreamReader und dann über von ReadLine zurückgegeben Zeilen iterieren.

      [HIGHLIGHT=C#]public static class FileCache
      {
      private static IEnumerable<string> lines = null;
      private static string lastPath = string.Empty;

      public static IEnumerable<string> ReadLine(string path)
      {
      if (path.Equals(lastPath, StringComparison.InvariantCultureIgnoreCase))
      return lines;
      lines = File.ReadAllLines(path);
      return lines;
      }
      }[/HIGHLIGHT]

      Comment


      • #4
        Hey,

        vielen Dank für eure Ratschläge! Also aus der Aufgabe (Teil einer Testklausur) sind leider keine weiteren Informationen zu entnehmen. Jedoch muss ich dazu sagen, dass es sich um das Modul "Datenstrukturen und Algorithmen" handelt. Soweit konnte ich dem Stoff gut folgen, nur mit dem yield, enumerator und enumerable hatte ich bisher tatsächlich noch Schwierigkeiten, dieses richtig zu verstehen.. Das war auch der Grund warum ich hier um Hilfe bat. Vielen Dank also für die Erläuterungen! ich werde mich fortan noch mal tiefergehender mit den Themen beschäftigen!

        Lieben Gruß

        Comment


        • #5
          Heyho,

          hier noch mal eine kurze Rückmeldung. Ich habe inzwischen einen Lösungsvorschlag vom Prof gefunden.

          [HIGHLIGHT=C#]namespace Sample
          {
          class Program
          {
          static void Main(string[] args)
          {
          foreach (var line in FileCache.ReadLine(@"c:\temp\1.txt"))
          Console.WriteLine(line);

          foreach (var line in FileCache.ReadLine(@"c:\temp\1.txt"))
          Console.WriteLine(line);
          }
          }

          class FileCache
          {
          static private string path;
          static List<string> list;

          static public IEnumerable<string> ReadLine(string path)
          {
          if (path.Equals(FileCache.path))
          return readFromCache();
          else
          {
          list = new List<string>();
          FileCache.path = path;
          return readFromMedium();
          }
          }

          static private IEnumerable<string> readFromCache()
          {
          foreach (var line in FileCache.list)
          yield return line;
          }

          static private IEnumerable<string> readFromMedium()
          {
          var r = new StreamReader(path);

          string line;

          while ((line = r.ReadLine()) != null)
          {
          list.Add(line);
          yield return line;
          }

          r.Close();
          }
          }
          }
          [/highlight]

          Lieben Gruß

          Comment


          • #6
            Wenn du deinen Prof nerven willst.

            a.) String.Equals ist casesensitiv was die meisten Filesysteme, zumindest die Windows üblichen, nicht sind.
            b.) readFromMedium ist gefährlich um nicht zu sagen falsch. Sollte jemand das iterieren mittendrin abbrechen hast du ein halbes File im Cache ohne das der Cache das weiss.

            Ändere z.B. die Main mal so

            [Highlight=C#]foreach (var line in FileCache.ReadLine(@"c:\temp\1.txt"))
            {
            Console.WriteLine(line);
            break;
            }

            foreach (var line in FileCache.ReadLine(@"c:\temp\1.txt"))
            Console.WriteLine(line);[/Highlight]

            Comment


            • #7
              Heieiei... und natürlich alles schön static mit Zustand drin. *IronieAn* Da lernt man gutes Programmieren *IronieAus*

              Comment

              Working...
              X