Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Λίγο που έχω ασχοληθεί με το Xml προτιμούσα να φτιάξω κάποιο XML με τον κλασικό τρόπο, χωρίς Serialization δηλαδή.

 

Τώρα έχει πάρει το μάτι μου ότι υπάρχει μια μέθοδος όπου μπορείς να κάνεις Serialization όλη την κλάση.

 

ΥΓ: πως κάνω ovveride? δηλαδή να διαβάσω κάτι που υπάρχει, να κάνω τις αλλαγές που θέλω και να το αποθηκεύσω χωρίς να μου δημιουργήσει νέο.

 

αν κάνε to StreamWriter να κάνει Append το αρχείο θα έχω το πρόβλημα ότι θα σβήνονται και πράγματα που δεν θέλω να σβηστούν.

 

Πχ. έχω ένα Xml που έχει τα όπλα , θέλω να κάνω μόνο μια αλλαγή στο όπλο με id=1 , αν κάνω append θα αλλάξει και το 2 :(

<Weapons>

    <Weapon id=1> ...</Weapon>
    <Weapon id=2> ...</Weapon>

</Wepons>

 

 

Ένα παράδειγμα

using System.Xml.Serialization;
using System.IO;

namespace xmlSerialize
{
    public class Player
    {
        public string   Name;
        public int      Level;
        public float    Health;
        public float    Mana;

        public Player() { }
        public Player(string _name, int _level, float _hp, float _mp)
        {
            Name = _name;
            Level = _level;
            Health = _hp;
            Mana = _mp;
        }
    };

    class Program
    {
        static void Main(string[] args)
        {
            Player p = new Player("DarkHero", 1, 200, 100);

            StreamWriter sw = new StreamWriter(@"myXml.xml");

            XmlSerializer xml = new XmlSerializer(p.GetType());
            xml.Serialize(sw, p);

        }
    }

}

Output

<?xml version="1.0" encoding="utf-8"?>
<Player xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Name>DarkHero</Name>
  <Level>1</Level>
  <Health>200</Health>
  <Mana>100</Mana>
</Player>
Δημοσ.

Ολοκληρο το Stream το διαβάζεις και ολοκληρο το ξανα αποθηκευεις (αφου κανεις αλλαγες).

        public void Save(Player p)
        {
            XmlSerializer x = new XmlSerializer(typeof(Player));
            x.Serialize(new FileStream("c:\\myFile", FileMode.CreateNew), p);
        }

        public Player Load()
        {
            XmlSerializer x = new XmlSerializer(typeof(Player));
            return (Player)x.Deserialize(new FileStream("c:\\myFile", FileMode.Open));
        }

Μπορεις να κανεις Serialize collection απο Player αν εχεις πολλους.

Δημοσ.

Ολοκληρο το Stream το διαβάζεις και ολοκληρο το ξανα αποθηκευεις (αφου κανεις αλλαγες).

...
        public Player Load()
        {
            XmlSerializer x = new XmlSerializer(typeof(Player));
            return (Player)x.Deserialize(new FileStream("c:\\myFile", FileMode.Open));
        }

Μπορεις να κανεις Serialize collection απο Player αν εχεις πολλους.

 

η συνάρτηση αυτή επιστρέφει το περιεχόμενο της XML, δεν θα έπρεπε να επιστρέφει πίνακα?

 

δηλαδή Public Player[] Load() ? αν έχω 2 παίχτες και εκτελέσω τον κώδικα της συνάρτησης που έγραψες, πως θα πάρω αυτό που θέλω μιας και η συνάρτησή σου επιστρέφει έναν παίχτη.

Δημοσ.

Την κανω να επιστρεφει πίνακα απο Players 

Αντικειμενο ειναι και ο πίνακας.

        public void Save(Player[] p)
        {
            XmlSerializer x = new XmlSerializer(typeof(Player[]));
            x.Serialize(new FileStream("c:\\myFile", FileMode.CreateNew), p);
        }

        public Player[] Load()
        {
            XmlSerializer x = new XmlSerializer(typeof(Player[]));
            return (Player[])x.Deserialize(new FileStream("c:\\myFile", FileMode.Open));
        }

Player[] pls = Load();
pls[0].Level = 5;
pls[1].Name = "onoma";
Save(pls);
Δημοσ.

Αφου ξερεις τα elements και τις τιμες, φορτωσε ολο το κειμενο ως String, κανε ανζητηση, βρες το offset και γραψε μονο την τιμη που θες ν αλλαξει

  • Like 1
Δημοσ.

Αφου ξερεις τα elements και τις τιμες, φορτωσε ολο το κειμενο ως String, κανε ανζητηση, βρες το offset και γραψε μονο την τιμη που θες ν αλλαξει

 

Δεν αρκει η string.IndexOf() για να φτιάξεις xml parser απο το μηδεν.

Δημοσ.

Βασικα, δεν μπορεις να "αλλαξεις" μια τιμη σε ενα αρχειο xml. Θα το φορωσεις, θα αλλαξεις αυτο που θες και μετα θα το γραψεις παλι.

Δημοσ.

Βασικα, δεν μπορεις να "αλλαξεις" μια τιμη σε ενα αρχειο xml. Θα το φορωσεις, θα αλλαξεις αυτο που θες και μετα θα το γραψεις παλι.

Οταν εχεις ανοιξει ένα οποιοδήποτε αρχειο για γραψιμο

Αν ο κερσορας (Stream.Position) δεν ειναι στο τέλος του, η Write() καλυπτει τα bytes απο κει και κατω (δεν μπορεις να τα παρεμβάλεις).

Αν ειναι στο τέλος προσθετει νεα bytes.

Δημοσ.

Με οτι μεθοδο και να γίνει θα διαβαστει ολο και θα ξαναγραφει ολο. Σε θέματα settings δεν ειναι προβλήμα, δεν ειναι τόσο μεγαλα τα αρχεία. 

 

Εκτος αν ξερεις ότι η τιμη του πεδίου π.χ. Health ειναι παντα 3 bytes στις θεσεις 100, 101 102 και πας και γραφεις εκει την αλλαγή (εντελώς απιθανο). 

 

Η XmlSerializer δεν γραφει καθόλου τα πεδία αν εχουν την Default τιμή τους (ειναι μια μικρη εξοικονομηση χωρου).

Και το πιο σημαντικό, μπορεις να προσθεσεις νεα πεδία στην κλαση σου και να φορτώσεις xml αρχειο παλαιοτερης version που δεν τα ειχε.

Η και το αναποδο, να φορτώσεις αρχείο που εχει επιπλέον πεδία (απλα τα αγνοει).

Δημοσ.

Δεν ξέρω τι λέτε, εγώ βλέπω ότι δεν υπάρχει λόγος να φορτώσεις το xml σαν Stream και να κάνεις Search&Change.

 

Γίνονται όλα αυτόματα

 

Φορτώνω τα δεδομένα σε έναν πίνακα Player[] και μετά μπορώ να επέμβω ως εξής

p[index].Name = "Mitsos"
p[1].Name = "Mitsos"

Απλά αυτό που δεν μου αρέσει είναι ότι αυτόματα βάζει ένα όνομα ArrayOfClasName
(Τέσπα, δεν με πειράζει, αν και θα προτιμούσα Players αντί ArrayOfXXX)
 

 

πχ.

<?xml version="1.0"?>
<ArrayOfPlayer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Player>
    <Name>DarkHero</Name>
    <Level>1</Level>
    <Health>200</Health>
    <Mana>100</Mana>
  </Player>
  <Player>
    <Name>Jesus</Name>
    <Level>100</Level>
    <Health>99999</Health>
    <Mana>99999</Mana>
  </Player>
</ArrayOfPlayer>
Δημοσ.

Με οτι μεθοδο και να γίνει θα διαβαστει ολο και θα ξαναγραφει ολο. Σε θέματα settings δεν ειναι προβλήμα, δεν ειναι τόσο μεγαλα τα αρχεία. 

 

Εκτος αν ξερεις ότι η τιμη του πεδίου π.χ. Health ειναι παντα 3 bytes στις θεσεις 100, 101 102 και πας και γραφεις εκει την αλλαγή (εντελώς απιθανο). 

 

Η XmlSerializer δεν γραφει καθόλου τα πεδία αν εχουν την Default τιμή τους (ειναι μια μικρη εξοικονομηση χωρου).

Και το πιο σημαντικό, μπορεις να προσθεσεις νεα πεδία στην κλαση σου και να φορτώσεις xml αρχειο παλαιοτερης version που δεν τα ειχε.

Η και το αναποδο, να φορτώσεις αρχείο που εχει επιπλέον πεδία (απλα τα αγνοει).

Ειπα κι γω, νομιζα οτι ελεγες οτι μπορεις να κανεια append στη μεση του πουθενα...

 

τσ δες τα Attribute που εχει το xmlserializer, μπορεις να βαλεις οτι θες στην θεση του ArrayOfWhateva

Δημοσ.

Αυτό (κώδικας)

 

 

 

using System.Xml.Serialization;
using System.IO;
using System;
using System.Text;

namespace xmlSerialize
{
    public class Player
    {
        public string   Name;
        public int      Level;
        public float    Health;
        public float    Mana;

        public Player() { }
        public Player(string _name, int _level, float _hp, float _mp)
        {
            Name = _name;
            Level = _level;
            Health = _hp;
            Mana = _mp;
        }
    };

    class Program
    {
        static StringBuilder sb = new StringBuilder();

        static void Main(string[] args)
        {
            Player[] player = new Player[2];
            player[0] = new Player("DarkHero", 1, 200, 100);
            player[1] = new Player("Jesus", 100, 99999, 99999);

            //Save(p);
            player = Load();

            // Build Show-Data
            for (int i = 0; i < 2; i++)
            {
                sb.Append("\nName     : " + player[i].Name);
                sb.Append("\nLevel    : " + player[i].Level);
                sb.Append("\nHealth   : " + player[i].Health);
                sb.Append("\nMana     : " + player[i].Mana);
                sb.Append("\n\n------------------------------");
            }

            Console.WriteLine(sb);
        }

        public static void Save(Player[] p)
        {
            XmlSerializer x = new XmlSerializer(typeof(Player[]));
            x.Serialize(new FileStream(@"myXml2.xml", FileMode.CreateNew), p);
        }

        public static Player[] Load()
        {
            XmlSerializer x = new XmlSerializer(typeof(Player[]));
            return (Player[])x.Deserialize(new FileStream(@"myXml2.xml", FileMode.Open));
        }
    }

}

 

 

 

 

δίνει αυτό
 

image.png



Τόσο απλά!

 

πραγματικά το xmlSerializer τα σπάει, χρησιμοποιούσα πιο δύσκολη μέθοδο...

Δημοσ.

Δες και τα attributes

using System.Xml.Serialization;
using System.IO;
using System;
using System.Text;
using System.Collections.Generic;

namespace xmlSerialize
{
    public class Player
    {
        [XmlElement( "name")]
        //anti gia Name 8a exei name
        public string Name;

        public int Level;
        public float Health;
        public float Mana;

        [XmlAttribute("player-id")]
        //ayto den 8a einai element alla attribute
        public int Id { get; set; }

        public Player() { }
        public Player(string _name, int _level, float _hp, float _mp, int id)
        {
            Name = _name;
            Level = _level;
            Health = _hp;
            Mana = _mp;
            this.Id = id;
        }
    };
    [XmlRoot("root")]
    public class Root
    {
        [XmlArray("players")]
        //anti gia arrayof 8a exei players
        [XmlArrayItem("player")]
        //kai to ka8e elem 8a legetai player
        public List<Player> Players { get; set; }
        
        
        [XmlIgnore]
        //ayto den 8a ginei serializable
        public List<int> fooListNotInXML { get; set; }

        public Root()
        {
            fooListNotInXML = new List<int>();
            Players = new List<Player>();
        }
        public static Root Load(Stream stream)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            return serializer.Deserialize(stream) as Root;
        }
        public void Save(Stream stream)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Root));
            serializer.Serialize(stream, this);
        }
    }

    class Program
    {
        static StringBuilder sb = new StringBuilder();

        static void Main(string[] args)
        {
            /*
            Player[] player = new Player[2];
            player[0] = new Player("DarkHero", 1, 200, 100);
            player[1] = new Player("Jesus", 100, 99999, 99999);

            //Save(p);
            player = Load();
             

            // Build Show-Data
            for (int i = 0; i < 2; i++)
            {
                sb.Append("\nName     : " + player[i].Name);
                sb.Append("\nLevel    : " + player[i].Level);
                sb.Append("\nHealth   : " + player[i].Health);
                sb.Append("\nMana     : " + player[i].Mana);
                sb.Append("\n\n------------------------------");
            }

            Console.WriteLine(sb);
             */

            Root root = new Root();
            root.Players.Add(new Player("DarkHero", 1, 200, 100,1));
            root.Players.Add(new Player("Jesus", 100, 99999, 99999,2));
            using (var fp = File.Open("foo.xml", FileMode.OpenOrCreate))
            {
                root.Save(fp);
            }
            using (var fp = File.Open("foo.xml",FileMode.OpenOrCreate))
            {
                Root otherRoot = Root.Load(fp);
                foreach (var player in otherRoot.Players)
                {
                    Console.WriteLine(
                       "Name:\t{0}\nLevel:\t{1}\nHealth:\t{2}\nMana:\t{3}\n",
                       player.Name,
                       player.Level,
                       player.Health,
                       player.Mana
                        );
                }
            }
            Console.Read();
        }

        
    }

}
<?xml version="1.0"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <players>
    <player player-id="1">
      <name>DarkHero</name>
      <Level>1</Level>
      <Health>200</Health>
      <Mana>100</Mana>
    </player>
    <player player-id="2">
      <name>Jesus</name>
      <Level>100</Level>
      <Health>99999</Health>
      <Mana>99999</Mana>
    </player>
  </players>
</root>
  • Like 1

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...