sonyxp Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Λίγο που έχω ασχοληθεί με το 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>
albNik Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Ολοκληρο το 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 αν εχεις πολλους.
sonyxp Δημοσ. 1 Σεπτεμβρίου 2013 Μέλος Δημοσ. 1 Σεπτεμβρίου 2013 Ολοκληρο το 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 παίχτες και εκτελέσω τον κώδικα της συνάρτησης που έγραψες, πως θα πάρω αυτό που θέλω μιας και η συνάρτησή σου επιστρέφει έναν παίχτη.
albNik Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Την κανω να επιστρεφει πίνακα απο 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);
nilosgr Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Αφου ξερεις τα elements και τις τιμες, φορτωσε ολο το κειμενο ως String, κανε ανζητηση, βρες το offset και γραψε μονο την τιμη που θες ν αλλαξει 1
albNik Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Αφου ξερεις τα elements και τις τιμες, φορτωσε ολο το κειμενο ως String, κανε ανζητηση, βρες το offset και γραψε μονο την τιμη που θες ν αλλαξει Δεν αρκει η string.IndexOf() για να φτιάξεις xml parser απο το μηδεν.
παπι Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Βασικα, δεν μπορεις να "αλλαξεις" μια τιμη σε ενα αρχειο xml. Θα το φορωσεις, θα αλλαξεις αυτο που θες και μετα θα το γραψεις παλι.
albNik Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Βασικα, δεν μπορεις να "αλλαξεις" μια τιμη σε ενα αρχειο xml. Θα το φορωσεις, θα αλλαξεις αυτο που θες και μετα θα το γραψεις παλι. Οταν εχεις ανοιξει ένα οποιοδήποτε αρχειο για γραψιμο Αν ο κερσορας (Stream.Position) δεν ειναι στο τέλος του, η Write() καλυπτει τα bytes απο κει και κατω (δεν μπορεις να τα παρεμβάλεις). Αν ειναι στο τέλος προσθετει νεα bytes.
παπι Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Ναι.... και τι θελει να πει ο ποιητης; Οτι μπορεις να αλλαξεις μια τιμη ή οτι δεν μπορεις;
albNik Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Με οτι μεθοδο και να γίνει θα διαβαστει ολο και θα ξαναγραφει ολο. Σε θέματα settings δεν ειναι προβλήμα, δεν ειναι τόσο μεγαλα τα αρχεία. Εκτος αν ξερεις ότι η τιμη του πεδίου π.χ. Health ειναι παντα 3 bytes στις θεσεις 100, 101 102 και πας και γραφεις εκει την αλλαγή (εντελώς απιθανο). Η XmlSerializer δεν γραφει καθόλου τα πεδία αν εχουν την Default τιμή τους (ειναι μια μικρη εξοικονομηση χωρου). Και το πιο σημαντικό, μπορεις να προσθεσεις νεα πεδία στην κλαση σου και να φορτώσεις xml αρχειο παλαιοτερης version που δεν τα ειχε. Η και το αναποδο, να φορτώσεις αρχείο που εχει επιπλέον πεδία (απλα τα αγνοει).
sonyxp Δημοσ. 1 Σεπτεμβρίου 2013 Μέλος Δημοσ. 1 Σεπτεμβρίου 2013 Δεν ξέρω τι λέτε, εγώ βλέπω ότι δεν υπάρχει λόγος να φορτώσεις το 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>
παπι Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Με οτι μεθοδο και να γίνει θα διαβαστει ολο και θα ξαναγραφει ολο. Σε θέματα settings δεν ειναι προβλήμα, δεν ειναι τόσο μεγαλα τα αρχεία. Εκτος αν ξερεις ότι η τιμη του πεδίου π.χ. Health ειναι παντα 3 bytes στις θεσεις 100, 101 102 και πας και γραφεις εκει την αλλαγή (εντελώς απιθανο). Η XmlSerializer δεν γραφει καθόλου τα πεδία αν εχουν την Default τιμή τους (ειναι μια μικρη εξοικονομηση χωρου). Και το πιο σημαντικό, μπορεις να προσθεσεις νεα πεδία στην κλαση σου και να φορτώσεις xml αρχειο παλαιοτερης version που δεν τα ειχε. Η και το αναποδο, να φορτώσεις αρχείο που εχει επιπλέον πεδία (απλα τα αγνοει). Ειπα κι γω, νομιζα οτι ελεγες οτι μπορεις να κανεια append στη μεση του πουθενα... τσ δες τα Attribute που εχει το xmlserializer, μπορεις να βαλεις οτι θες στην θεση του ArrayOfWhateva
sonyxp Δημοσ. 1 Σεπτεμβρίου 2013 Μέλος Δημοσ. 1 Σεπτεμβρίου 2013 Αυτό (κώδικας) 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)); } } } δίνει αυτό Τόσο απλά! πραγματικά το xmlSerializer τα σπάει, χρησιμοποιούσα πιο δύσκολη μέθοδο...
παπι Δημοσ. 1 Σεπτεμβρίου 2013 Δημοσ. 1 Σεπτεμβρίου 2013 Δες και τα 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> 1
nilosgr Δημοσ. 2 Σεπτεμβρίου 2013 Δημοσ. 2 Σεπτεμβρίου 2013 Ναι οντως, αυτο που ειπα ισχυει μονο αν ειχαν συγκεκριμενο μηκος οι τιμες των element
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα