Serializacja XML, zerowanie się zmiennych

0

Witam wszystkich! Mam problem, a mianowicie nie chce mi poprawnie serializować i deserializować pliku XML. Udało mi się doprowadzić do tego, że program się uruchamia (!), ale podczas serializacji w nowo powstałym pliku XML wartości zmiennych są wyzerowane :/ Może ktoś z Was szybko wyłapie gdzie robię błąd? Poniżej kod:

[XmlRoot("pomiar")]
    public class Moja_klasa
    {
        [XmlElement("data")]
        public DateTime data { get; set; }
        [XmlElement("temperatura")]
        public double temperatura { get; set; }
        [XmlElement("cisnienie")]
        public double cisnienie { get; set; }

        public Moja_klasa()
        {
        }

        public Moja_klasa(DateTime sdata, double ftemperatura, double fcisnienie)
        {
            data = sdata;
            temperatura = ftemperatura;
            cisnienie = fcisnienie;
        }

        public void DeserializeObject(string filename)
        {
            // Create an instance of the XmlSerializer specifying type and namespace.
            XmlSerializer serializer = new XmlSerializer(typeof(Moja_klasa));

            // A FileStream is needed to read the XML document.
            FileStream fs = new FileStream(filename, FileMode.Open);
            XmlReader reader = XmlReader.Create(fs);

            // Use the Deserialize method to restore the object's state.
            List<Moja_klasa> lista = new List<Moja_klasa>
            { };

            Moja_klasa i = (Moja_klasa)serializer.Deserialize(reader);
            fs.Close();

            // Write out the properties of the object.
        }
        public void SerializeObject(Moja_klasa o,StreamWriter wr)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Moja_klasa));
            serializer.Serialize(wr, o);
            wr.Flush();
            wr.Close();
        } 

A tak jest to wywolywane w main:

try
            {
                Moja_klasa t = new Moja_klasa();
                t.DeserializeObject("C:\\Users\\Marcin\\Desktop\\obiekt\\iks.xml");
                listBox1.Items.Add("data: "+t.data);

                StreamWriter wr = new StreamWriter("C:\\Users\\Marcin\\Desktop\\obiekt\\apa.xml");
                t.SerializeObject(t, wr);
            } 

Tutaj zawartość prostego XML, którego chcę zDEserializować i poźniej na podstawie otrzymanego obiektu utworzyć nowy XML (zserializować).

 <?xml version="1.0" encoding="ISO-8859-2" standalone="no"?>
 
<pomiar>
    <data>2015-12-12T14:12:11</data>
    <temperatura>20.00</temperatura>
    <cisnienie>15.00</cisnienie> 
</pomiar>
0

A jesteś pewny że działa czy deserializacja? Bo wydaje mi się, jeśli nie ukryłeś żadnego kodu, że tam tworzysz tylko nowy obiekt, ale nie przypisujesz do obecnego, który chyba chciałbyś.

Do tego paskudne nazewnictwo, zapoznaj się ze standardami.

1

Widze gdzie jest blad ale pozwole Ci samemu do niego dojsc zebys sie czegos nauczyl.
Usun metody DeserializeObject i SerializeObject i wrzuc caly kod serializacji i deserializacji do main (czy skadkolwiek wywolujesz). Jak to zrobisz to uprosc kod najbardziej jak sie da. Potem zastanow sie czemu ta wersja dziala a ta z metodami nie. Jak dalej nie wiesz to teraz dodaj metode do serializacji i przenos po jednej linii do srodka i zastanow sie co sie zmienia i w ktorym momencie przestaje dzialac

0

OK, teraz bez używania tych metod odczytuje xml-a i jest w porządku. Teraz chciałbym zrobić deserializowanie xml do listy obiektów. na razie mam takie coś:

  // Create an instance of the XmlSerializer specifying type and namespace.
                XmlSerializer deserializer = new XmlSerializer(typeof(Moja_klasa));
                FileStream fs = new FileStream(("C:\\Users\\Marcin\\Desktop\\obiekt\\iks.xml"), FileMode.Open);
                XmlReader reader = XmlReader.Create(fs);
                List<Moja_klasa> lista = new List<Moja_klasa>();

                Moja_klasa i = (Moja_klasa)deserializer.Deserialize(reader);
                lista.Add(i);
                fs.Close();

                foreach (Moja_klasa obiekcik in lista)
                {
                    listBox1.Items.Add("Data: " + obiekcik.data + "\r\n");
                    listBox1.Items.Add("Temperatura: " + obiekcik.temperatura + "\r\n");
                    listBox1.Items.Add("Cisnienie: " + obiekcik.cisnienie + "\r\n");
                }

                XmlSerializer serializer = new XmlSerializer(typeof(Moja_klasa));
                StreamWriter wr = new StreamWriter("C:\\Users\\Marcin\\Desktop\\obiekt\\apa.xml");
                serializer.Serialize(wr, i);
                wr.Flush();
                wr.Close();

Plik klasy taki sam jak wyżej. Nie chce mi działać przy ilosci danych w xml wystarczajacej dla wiecej niz jednego obiektu, np. przy takim xml:

 <?xml version="1.0" encoding="ISO-8859-2" standalone="no"?>
 
<pomiar>
    <data>2015-12-12T14:12:11</data>
    <temperatura>20.00</temperatura>
    <cisnienie>15.00</cisnienie>
 
    <data>2010-11-11T14:00:11</data>
    <temperatura>25.00</temperatura>
    <cisnienie>13.00</cisnienie>
</pomiar> 

Wpadłem też na to, że może ten plik xml jest zle zbudowany, dlatego troche go przerobiłem, żeby mieć każdą serię danych w oddzielnym "bloczku":

<?xml version="1.0" encoding="ISO-8859-2" standalone="no"?>
 
<pomiary>
    <pomiar>
    <data>2015-12-12T14:12:11</data>
    <godzina>14:12:11</godzina>
    <temperatura>20.00</temperatura>
    <cisnienie>15.00</cisnienie> 
    </pomiar>
    
    <pomiar>
    <data>2000-12-12T14:12:11</data>
    <godzina>14:00:11</godzina>
    <temperatura>10.00</temperatura>
    <cisnienie>25.00</cisnienie> 
    </pomiar>
</pomiary> 

Tylko teraz nie wiem jak mam odróżnić jedne dane od drugich przy deserializacji :/ Przepraszam z góry za mój niefachowy język, mam nadzieję, że zrozumiale wyjaśniłem problem.

1

W takiej wersji dziala, pobaw sie:

    public class pomiar
    {
        public DateTime data { get; set; }
        public double temperatura { get; set; }
        public double cisnienie { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<pomiar>), new XmlRootAttribute("pomiary"));
            List<pomiar> lista = (List<pomiar>)xmlSerializer.Deserialize(new StringReader(
@"<?xml version=""1.0"" ?>
<pomiary>
    <pomiar>
        <data>2015-12-12T14:12:11</data>
        <godzina>14:12:11</godzina>
        <temperatura>20.00</temperatura>
        <cisnienie>15.00</cisnienie> 
    </pomiar>

    <pomiar>
        <data>2000-12-12T14:12:11</data>
        <godzina>14:00:11</godzina>
        <temperatura>10.00</temperatura>
        <cisnienie>25.00</cisnienie> 
    </pomiar>
</pomiary>"));
            foreach (var pomiar in lista)
            {
                Console.WriteLine("       data=  {0}", pomiar.data);
                Console.WriteLine("temperatura=  {0}", pomiar.temperatura);
                Console.WriteLine("  cisnienie=  {0}", pomiar.cisnienie);
                Console.WriteLine("-----");
            }
        }
    }
0

Dziękuję, teraz jest OK! Jeżeli można, to teraz chciałbym zadać pytanie trochę z innej beczki. W jaki najprostszy sposób przesłać plik xml z serwera do klienta za pomocą połączenia TCP? Umiem ustanowić połączenie serwer-klient, ale nie mam pojęcia jak przesłać plik :/

1

najpierw obmysl w jaki sposob chcesz to wyslac. Wysylasz bajty wiec druga strona musi wiedziec jak to zinterpretowac.

Przyklad. Wysylasz binarnie:
<liczba bajtow><bajty>
przykladowo w C# juz jest BinaryWriter i BinaryReader ktore zrobia to za Ciebie:

// zastap swoim strumieniem
MemoryStream fakeSocket = new MemoryStream();

// bez znaczenia jakie kodowanie byle z dwoch stron bylo takie same (jak wyslesz BOM to druga strona nie musi znac kodowania bo w BOM jest zakodowane)
Encoding utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);

// fakowe wysylanie
BinaryWriter bw = new BinaryWriter(fakeSocket, utf8NoBom, leaveOpen: true);
bw.Write("asdf test test dfsfsdf");


// przewijamy do poczatku strumienia zeby zasymulowac odbieranie z drugiej strony
fakeSocket.Seek(0, SeekOrigin.Begin);


// fakowe odbieranie
BinaryReader br = new BinaryReader(fakeSocket, utf8NoBom, leaveOpen: true);
string message = br.ReadString();

Console.WriteLine(message);

jesli potrzebujesz wiecej kontroli nad tym co sie dzieje i jak zakodowana jest dlugosc to uzyj twoje kodowanie.GetBytes(string) do

0

Kolejnym problemem, z którym nie moge sobie poradzić jest to, że przy próbie pobrania pliku od strony klienta wyrzuca mi komunikat "nie można odczytać danych spoza końca strumienia". Poniżej kod wysyłania od strony serwera:

XmlDocument myxml = new XmlDocument();
            myxml.Load("C:\\Users\\Marcin\\Desktop\\obiekt\\iks.xml");
            StringWriter sw = new StringWriter();
            XmlTextWriter tx = new XmlTextWriter(sw);
            myxml.WriteTo(tx);
            string str = sw.ToString();

            MemoryStream fs = new MemoryStream();
            Encoding utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
            BinaryWriter bw = new BinaryWriter(fs, utf8NoBom, leaveOpen: true);
            bw.Write(str); 

Tutaj kod służący odbieraniu:

MemoryStream fk = new MemoryStream();
            Encoding utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);           
            BinaryReader br = new BinaryReader(fk, utf8NoBom, leaveOpen: true); 
            string message = br.ReadString();
            MessageBox.Show(message); 

Próbowałem z tym przewijaniem strumienia .Seek(0, SeekOrigin.Begin); ale na nic moje próby niestety. Proszę o jakąś podpowiedź :o
EDIT:
Dodam, że powyższy kod działa w przypadku fake'owej transmisji, czyli w ten sposób, który przedstawił krwq.

1

MemoryStream to byl przykladowy strumien, musisz ze strumienia czytac/pisac ktore z socketow dostales

0

Mam kolejny problem, nie mogę w żaden sposób dostosować tego kodu tak, żeby możliwe było używanie funkcji wysylania stringa przez np. button. Działa to tylko wtedy, gdy ta funkcja jest bezposrednio w metodzie dotyczacej asynchronicznego połączenia. Domyślam się, że gdzieś jest konflikt podczas uzyskiwania dostępu do może strumienia (?), ale nie mogę kurde tego błędu znaleźć.

using System;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private TcpListener serwer;
        public TcpClient klient;
        private delegate void SetTextCallBack(string tekst);
        BinaryWriter writer;

        private void SetListBoxText(string tekst)
        {
            if (listBox1.InvokeRequired)
            {
                SetTextCallBack f = new SetTextCallBack(SetListBoxText);
                this.Invoke(f, new object[] { tekst });
            }
            else
            {
                listBox1.Items.Add(tekst);
            }
        }



        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e) // start
        {
            int port = Convert.ToInt16(numericUpDown1.Value);

            

                listBox1.Items.Add("Oczekiwanie na połączenie...");
                IPAddress adresIP;
                try
                {
                    adresIP = IPAddress.Parse(textBox1.Text);
                }
                catch
                {
                    listBox1.Items.Add("Błędny format adresu IP!");
                    textBox1.Text = String.Empty;
                    return;
                }

                try
                {
                    TcpListener serwer = new TcpListener(adresIP,port);
                    serwer.Start();
                    serwer.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientCallback), serwer);
                }
                catch(Exception ex)
                {
                    listBox1.Items.Add("Błąd: "+ex.Message);
                }     
        }



        private void button2_Click(object sender, EventArgs e) // stop 
        {
            if (serwer != null) serwer.Stop();
        }






        public void AcceptTcpClientCallback(IAsyncResult asyncResult)
        {
            TcpListener s = (TcpListener)asyncResult.AsyncState;
            klient = s.EndAcceptTcpClient(asyncResult);
            SetListBoxText("Polaczenie ustanowione!");

           
            klient.Close();
            // serwer.Stop(); 
        }

        private void button5_Click(object sender, EventArgs e) // tutaj chcialbym wywolywac writer'a
        {
            XmlDocument myxml = new XmlDocument();
            myxml.Load("C:\\Users\\Marcin\\Desktop\\obiekt\\iks.xml");
            StringWriter sw = new StringWriter();
            XmlTextWriter tx = new XmlTextWriter(sw);
            myxml.WriteTo(tx);
            string str = sw.ToString();

            writer = new BinaryWriter(klient.GetStream());
            writer.Write(str);

        }
    }
}
 

1 użytkowników online, w tym zalogowanych: 0, gości: 1