Forum: PC-Programmierung C#: Problem beim Einlesen von XML


von Andreas (Gast)


Lesenswert?

Hallo,
in meinem Programm möchte ich Daten in eine XML-Datei schreiben und 
lesen. Schreiben funktioniert soweit.
Jedoch habe ich beim Einlesen folgenden Fehler: Information wird 
eingelesen, in Instanz "tempProject" gespeichert, "tempProject" wird in 
Liste "ListProjectsLoaded" abgelegt. Da immer in die gleiche Instanz 
"tempProject" eingelesen wird, habe ich am Ende x-mal die gleichen 
Informationen in "ListProjectsLoaded".
1
        public List<Project> LoadXml()
2
        {
3
            XmlTextReader reader = new XmlTextReader(Application.StartupPath + "\\XML\\save.xml");
4
            Project tempProject = new Project();
5
6
            ListProjectsLoaded.Clear();
7
8
            int i = 0;
9
            while (reader.Read())
10
            {
11
                switch (reader.Name)
12
                {
13
                    case "Name":
14
                        if (reader.NodeType == XmlNodeType.EndElement)
15
                            break;
16
                        reader.Read();
17
                        tempProject.Name = reader.Value;
18
                        break;
19
20
                    case "spent_Time":
21
                        if (reader.NodeType == XmlNodeType.EndElement)
22
                            break;
23
                        reader.Read();
24
                        tempProject.spentTime.Elapsed.Add(TimeSpan.Parse(reader.Value));
25
                        ListProjectsLoaded.Add(tempProject);
26
                        ListProjectsLoaded[i] = tempProject;
27
                        i++;
28
                        break;
29
                }
30
            }
31
            reader.Close();
32
33
            return ListProjectsLoaded;
34
        }


Fällt jemanden dazu eine Lösung ein?

von eugler (Gast)


Lesenswert?

Was soll das:
1
ListProjectsLoaded.Add(tempProject);
2
ListProjectsLoaded[i] = tempProject;

Zeig mal das XML.

von bluppdidupp (Gast)


Lesenswert?

Dein Problem ist:
1
ListProjectsLoaded.Add(tempProject);
2
tempProject=new Project(); // <-- Fehlt
3
ListProjectsLoaded[i] = tempProject; // <--- Unnütz da ListProjectsLoaded[i] schon vorher identisch mit tempProject ist ;D
Wenn du immer dieselbe tempProject-Instanz benutzt (quasi nicht 
zwischendurch mal ein neues tempProject erzeugt wird) brauchst du dich 
nicht wundern das deine Liste voll mit immer der gleichen Instanz ist ;D

von Andreas (Gast)


Lesenswert?

Danke! hab das jetz umgebaut. Funktioniert auch soweit. Jedoch hab ich 
jetzt noch einen anderen Fehler gefunden :/

Mein Code sieht jetzt folgendermaßen aus:
1
public List<Project> LoadXml()
2
        {
3
            XmlTextReader reader = new XmlTextReader(Application.StartupPath + "\\XML\\save.xml");
4
5
            ListProjectsLoaded.Clear();
6
7
            int i = 0;
8
            while (reader.Read())
9
            {
10
                switch (reader.Name)
11
                {
12
                    case "Name":
13
                        if (reader.NodeType == XmlNodeType.EndElement)
14
                            break;
15
                        ListProjectsLoaded.Add(new Project());
16
                        reader.Read();
17
                        ListProjectsLoaded[i].Name = reader.Value;
18
                        break;
19
20
                    case "spent_Time":
21
                        if (reader.NodeType == XmlNodeType.EndElement)
22
                            break;
23
                        reader.Read();
24
                        string[] spentTimeSplit = new string[3];
25
                        spentTimeSplit = reader.Value.Substring(0,8).Split(':');
26
27
                        TimeSpan AlreadySpentTime = new TimeSpan(
28
                            System.Convert.ToInt32(spentTimeSplit[0]),
29
                            System.Convert.ToInt32(spentTimeSplit[1]),
30
                            System.Convert.ToInt32(spentTimeSplit[2]));
31
32
                        ListProjectsLoaded[i].spentTime.Elapsed.Add(AlreadySpentTime);
33
                        i++;
34
                        break;
35
                }
36
            }
37
            reader.Close();
38
39
            return ListProjectsLoaded;
40
        }

In dieser Zeile sollte die eingelesene Zeit dem Stopwatch Objekt 
"spentTime" zugewiesen werden:
1
ListProjectsLoaded[i].spentTime.Elapsed.Add(AlreadySpentTime);

Obwohl "AlreadySpentTime" (meiner Meinung nach) im richtigen Format 
vorliegt, funktioniert es nicht. Die Stopuhr bleibt immer auf der Zeit 
"00:00:00". Woran kann das liegen? ist "spentTime.Elapsed.add()" die 
falsche Methode für meinen Verwendungszweck?


Hier noch das XML-File:
1
- <Attendance_Clock>
2
  - <Project>
3
      <Name>test1</Name> 
4
      <spent_Time>00:00:06.4156572</spent_Time> 
5
    </Project>
6
  - <Project>
7
      <Name>test2</Name> 
8
      <spent_Time>00:00:04.0817356</spent_Time> 
9
    </Project>
10
  - <Project>
11
      <Name>test3</Name> 
12
      <spent_Time>00:00:05.6005613</spent_Time> 
13
    </Project>
14
  - <Project>
15
      <Name>test4</Name> 
16
      <spent_Time>00:00:03.3043114</spent_Time> 
17
    </Project>
18
  </Attendance_Clock>

von bluppdidupp (Gast)


Lesenswert?

.Elapsed ist eigentlich ein read-only(!) Attribut der StopWatch.
Wenn du .Elapsed.Add() aufrufst, wird ein neues TimeSpan Objekt erzeugt 
das nirgends verwendet wird:
1
TimeSpan Elapsed=new TimeSpan();
2
TimeSpan neuesTimeSpan=Elapsed.Add(AlreadySpentTime;
3
// Elapsed ist unverändert!
4
// neuesTimeSpan ist Elapsed + AlreadySpentTime

Die StopWatch zählt im Normfall ElapsedTime einfach nur hoch wenn 
Start() aufgerufen wurde und friert ElapsedTime quasi bei .Stop() dann 
ein, so dass man sehen kann wielange der Krempel zwischen Start() und 
Stop() gebraucht hat.

Die StopWatch-Klasse kann man quasi dafür verwenden die Werte zu 
ermitteln, die du in deiner XML ja bereits hast ;D

Was hast du mit spent_Time denn vor, vllt. kann man was vorschlagen...

von Andreas (Gast)


Lesenswert?

Danke für deine Antwort!

Folgende Funktion erreicht werden:

Mit Klick auf Button "Start" wird Stopuhr gestartet.
Mit Klick auf Button "Stop" wird Stopuhr gestoppt. Soweit, Soklar.

Nun möchte ich aber bei beenden des Programmes den aktuelle Zeit der 
Stopuhr speichern (in XML) und beim nächsten Programmstart soll die 
bereits gemessene Zeit wieder geladen werden. Bei erneutem Klick auf 
Button "Start" soll Stopuhr wieder dort weiterzählen wo sie vor Beenden 
des Programmes stehen geblieben ist.


Gib es keine Möglichkeit einen Startwert/Offset für die Stopuhr zu 
definieren?

von bluppdidupp (Gast)


Lesenswert?

Du kannst dir einfach selbst ne StopWatch bauen:
1
public class StopWatch2
2
    {
3
        private DateTime startTime;
4
        private bool startTimeValid=false;
5
        private TimeSpan totalElapsed=new TimeSpan();
6
7
        /// <summary>
8
        /// StopWatch starten
9
        /// </summary>
10
        public void Start()
11
        {
12
            startTime = DateTime.Now;
13
            startTimeValid=true;
14
        }
15
16
        /// <summary>
17
        /// Stopwatch stoppen
18
        /// </summary>
19
        public void Stop()
20
        {
21
            if (!startTimeValid)
22
            {
23
                throw new Exception("Stop() ohne Start() ist Blödsinn ;D");
24
            }
25
26
            // Zeit zwischen Start() + Stop() messen:
27
            TimeSpan elapsedTime = DateTime.Now - startTime;
28
29
            // auf insgesamt vergangene Zeit drauf rechnen:
30
            totalElapsed += elapsedTime;
31
32
            startTimeValid = false;
33
        }
34
35
        /// <summary>
36
        /// Bereits vergangene Zeit lesen/setzen
37
        /// </summary>
38
        public TimeSpan ElapsedTime
39
        {
40
            get
41
            {
42
                return totalElapsed;
43
            }
44
            set
45
            {
46
                totalElapsed = value;
47
            }
48
        }
49
    }
Usage:
1
StopWatch2 sw=new StopWatch2();
2
sw2.Elapsed=new TimeSpan(12,0,0); // 12min sind bereits vergangen
3
sw2.Start();
4
// 3 Sekunden irgendwas tun
5
sw2.Stop();
6
Console.WriteLine(sw2.Elapsed); // gibt jetzt 12m, 3s aus

von Arc N. (arc)


Lesenswert?

Problem ist zwar gelöst, aber noch ein paar Anmerkungen:
- Application.StartupPath + "\\XML\\save.xml" klingt so, als ob in dem 
Verzeichnis auch geschrieben werden soll. Falls das der Fall ist: Das 
ist seit Ewigkeiten absolutes No-Go
http://msdn.microsoft.com/de-de/library/system.environment.specialfolder.aspx
- Ist das XML(-Format) vorgegeben? Man könnte auch direkt mit einem 
Typed-Dataset arbeiten 
http://www.codeproject.com/KB/XML/xmltocsharpclasses.aspx oder die 
Objekte direkt als XML serialisieren
http://msdn.microsoft.com/en-us/library/182eeyhh(v=VS.100).aspx

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.