简体   繁体   中英

Using filestreams and dictionary<string, string> in C# with Binary Formatter doesn't seem to work properly.

Basically i'm trying to serialize a dictionary<string, string> object into a file, and load it back later. I know I'm probably doing something wrong here. (and yes this is an irc bot ). The issue is that the full contents of the dictionary isn't saving to the file and in my debug window i'm getting the "didn't save" text which means It probably hasn't. It also crashes sometimes (leaves chat then returns) That's all I can really say on the matter.. if there's something I"m doing wrong i think it's probably to do with my nested statements or a file handler not being dealt with in the correct manner.

I do have two parent functions, save and load, but the compiler doesn't like me calling them from within the IRCBOT CLASS Here is the full code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
/* 
* This program establishes a connection to irc server and joins a channel. Thats it.
*
* Coded by Pasi Havia 17.11.2001 http://koti.mbnet.fi/~curupted
*
* Updated / fixed by Blake 09.10.2010
*/
class IrcBot
{


    //Save the file
    public bool SaveFile(string fullpath = Filename)
    {
        try
        {
            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = File.Create(fullpath);
            formatter.Serialize(stream, C);
            stream.Close();
        }
        catch
        {
            return false;
        }

        return true;
    }

    //Load a file
    public bool LoadFile(string fullpath = Filename)
    {
        try
        {
            if (!File.Exists(fullpath))
                return false;

            BinaryFormatter formatter = new BinaryFormatter();
            FileStream stream = File.OpenRead(fullpath);
            C = (Dictionary<string, string>)formatter.Deserialize(stream);
            stream.Close();
        }
        catch
        {
            return false;
        }

        return true;
    }


    // Irc server to connect 
    public static string SERVER = "irc.caffie.net";
    // Irc server's port (6667 is default port)
    private static int PORT = 6667;
    // User information defined in RFC 2812 (Internet Relay Chat: Client Protocol) is sent to irc server 
    private static string USER = "USER IrcBot 0 * :IrcBot";
    // Bot's nickname
    private static string NICK = "Pinkbot";
    // Channel to join
    private static string CHANNEL = "#testingbots";
    //The dictionary for messages
   // private Dictionary<int, string> D = new Dictionary<int, string>();
    public static Dictionary<string, string> C = new Dictionary<string, string>();


    public const string fullpath = "bot_knowledge.txt";
    public const string Filename = "bot_knowledge.txt";
    public static StreamWriter writer;
    static bool responded;
    static bool shutup;


    private static void Add_Response(string a, string b)
    {

        C.Add(a, b);


    }





    public static void Main(string[] args)
    {
        NetworkStream stream;
        TcpClient irc;
        string inputLine;
        StreamReader reader;
        try
        {

            //C.Add("what's up?", "nothing much");
           // C.Add("meep", "mope");
           // C.Add("hey", "what?");
           // C.Add("what is", "it's two. ");
           // C.Add("This", "that");
           // C.Add("okay", "it is okay.");
           // C.Add("is it?", "yeah..");
           // C.Add("who are you", "I'm a bot");
           // C.Add("Who are you?", "I am a bot");
          //  C.Add("not you", "oh I'm sorry");
           // C.Add("what?", "nothing... just processing");
           // C.Add("What?", "nothing just you know. :3");
           // C.Add("help", "With ? ");
           // C.Add("help me", "I can't I'm a bot.");
            //C.Add("hm", "thinking deeply about something are we?");
           // C.Add("yes", "oh no. ");
          //  C.Add("no", "OHHHH YESSS");
          //  C.Add("super mario world", "yes");
           // C.Add("SMWC", "That's this place.. isn't it?");
          //  C.Add("smwc", "on our website!");
           // C.Add("lol", "AHAHAHAHAHAHAHA!");
           // C.Add("lel", "It's LOL");
          //  C.Add("!help", "use '!'shutup or '!'reset to change states omit '' see help2 for more"); 
          //  C.Add("!help2", "usage of '!'add is '!add' <yourphrasehere> '!'and <yoursecond phrase here> omit the ' ' ");



            irc = new TcpClient(SERVER, PORT);
            stream = irc.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);
            writer.WriteLine("NICK " + NICK);
            writer.Flush();
            writer.WriteLine(USER);
            writer.Flush();
            while (true)
            {
                while ((inputLine = reader.ReadLine()) != null)
                {


                    if (inputLine.Contains("!shutup"))
                    {

                        shutup = true;
                    }



                    Console.WriteLine("<-" + inputLine);


                    //=======Here data is saved or loaded manually======//
                    if (inputLine.Contains("!load"))
                    {
                        try
                        {
                            BinaryFormatter formatter = new BinaryFormatter();
                            FileStream st = File.OpenRead(fullpath);
                            C = (Dictionary<string, string>)formatter.Deserialize(st);
                            st.Close();
                        }

                        catch
                        {

                            Console.WriteLine("Didn't load");

                        }
                        writer.WriteLine("PRIVMSG " + CHANNEL + " :Data was loaded, presumably." + "\r\n");
                        writer.Flush();

                    }

                    if (inputLine.Contains("!save"))
                    {
                        try
                        {
                            BinaryFormatter formatter = new BinaryFormatter();
                            if (File.Exists(fullpath))
                            {
                                FileStream sa = File.OpenWrite(fullpath);
                                formatter.Serialize(sa, C);
                                sa.Close();
                            }
                            else
                                File.Delete(fullpath);
                                    FileStream sc = File.Create(fullpath);
                                    formatter.Serialize(sc, C);
                                    sc.Close();



                        }
                        catch
                        {


                            Console.WriteLine("Wasn't saved...");
                        }

                        writer.WriteLine("PRIVMSG " + CHANNEL + " :Data was saved, presumably." + "\r\n");
                        writer.Flush();

                    }




                    //==============================================//


                    if (inputLine.Contains("!add"))
                    {

                        string[] parts = inputLine.Split(new Char[] { ' ' });
                        int x = parts.Count();
                        int splitstart = 0;
                        string a = "";
                        string b = "";
                        for (int t = 4; t < x; t++)
                        {

                            if (parts[t] == "!and")
                            {
                                splitstart = t;
                                break;
                            }
                            if (t == 4)
                            {
                                a = a + parts[t];
                            }
                            else

                                a = a + " " + parts[t];


                        }



                        //now that i found splitstart i can do this

                        if (splitstart > 0)
                        {

                            for (int tt = splitstart+1; tt<x; tt++)
                            {
                                if (tt == splitstart + 1)
                                {
                                    b = b + parts[tt];
                                }
                                else
                                    b = b + " " + parts[tt];
                            }

                            Add_Response(a, b);
                            writer.WriteLine("PRIVMSG " + CHANNEL + " :added " +a+" ->"+b+" to my dictionary"+ "\r\n");
                            writer.Flush();


                        }


                    }



                    if (responded == true)
                    {

                        responded = false;
                    }

                    // Split the lines sent from the server by spaces. This seems the easiest way to parse them.
                    string[] splitInput = inputLine.Split(new Char[] { ' ' });




                    foreach (string it in splitInput)
                    {

                        if (it.Contains("!reset"))
                        {

                            if (responded == true)
                            {
                                writer.WriteLine("PRIVMSG " + CHANNEL + " :variable 'responded' was set to true" + "\r\n");
                                writer.Flush();

                            }

                            if (responded == false)
                            {
                                writer.WriteLine("PRIVMSG " + CHANNEL + " :variable 'responded' was set to false" + "\r\n");
                                writer.Flush();

                            }


                            responded = false;
                            shutup = false;


                        }




                        //if (it.Contains("hello"))
                        //{
                        // writer.WriteLine("PRIVMSG " + CHANNEL + " :hey" + "\r\n");
                        //writer.Flush();
                        // }

                        if (responded == false)
                        {
                            if (!shutup)
                            {

                                foreach (KeyValuePair<string, string> entry in C)
                                {
                                    // Console.WriteLine("<- was split to part " + it);


                                    if (it.StartsWith(entry.Key))
                                    {

                                        string output = entry.Value;
                                        writer.WriteLine("PRIVMSG " + CHANNEL + " :" + output + "\r\n");
                                        writer.Flush();
                                        responded = true;




                                    }
                                    else


                                        if (inputLine.Contains(entry.Key))
                                        {
                                            string output = entry.Value;
                                            writer.WriteLine("PRIVMSG " + CHANNEL + " :" + output + "\r\n");
                                            writer.Flush();
                                            responded = true;

                                        }
                                }





                            }
                        }













                        }



                    if (splitInput[0] == "PING")
                    {
                        string PongReply = splitInput[1];
                        //Console.WriteLine("->PONG " + PongReply);
                        writer.WriteLine("PONG " + PongReply);
                        writer.Flush();

                        continue;
                    }

                    switch (splitInput[1])
                    {
                        // This is the 'raw' number, put out by the server. Its the first one
                        // so I figured it'd be the best time to send the join command.
                        // I don't know if this is standard practice or not.
                        case "001":
                            string JoinString = "JOIN " + CHANNEL;
                            writer.WriteLine(JoinString);
                            writer.Flush();
                            break;
                        case "002":

                            break;
                        default:
                            break;
                    }


                }



                // Close all streams
                writer.Close();
                reader.Close();
                irc.Close();
            }

        }
        catch (Exception e)
        {
            // Show the exception, sleep for a while and try to establish a new connection to irc server
            Console.WriteLine(e.ToString());
            Thread.Sleep(5000);
            string[] argv = { };
            Main(argv);
        }
    }
}

First of all, I'll have to say that this method of debugging (uploading code to your bot and observing its behavior) is extremely problematic, leaving you with with no information on what actually happens, what exceptions are thrown, and so forth. Is there a way for you to attach a debugger to the process, or save logs with more exception details?

Regardless, in this case, psychic debugging should be enough to help us. You're trying to serialize a Dictionary using a BinaryFormatter , which is unsupported. You can only use the BinaryFormatter to serialize types marked as [Serializable] , which Dictionary is not.

This is a well known limitation to the .NET 1.1/2.0 era serializers, and to get around it you'll have to either write a lot of custom code involving custom serialization, or else use a different, newer serialization engine, such as .NET 3.5's DataContractSerializer , originally developed for and shipped with WCF, which can serialize Dictionaries, but does so into XML, not into a binary format.

Your problem lies here:

                    try
                    {
                        BinaryFormatter formatter = new BinaryFormatter();
                        if (File.Exists(fullpath))
                        {
                            FileStream sa = File.OpenWrite(fullpath);
                            formatter.Serialize(sa, C);
                            sa.Close();
                        }
                        else
                            File.Delete(fullpath);
                                FileStream sc = File.Create(fullpath);
                                formatter.Serialize(sc, C);
                                sc.Close();



                    }
                    catch
                    {


                        Console.WriteLine("Wasn't saved...");
                    }

First, your if/else cases are backwards: you call File.Delete for the case where the file doesn't exist.

Second, the else block is missing curly brackets, so your control flow will be incorrect.

I will leave the corrections as the proverbial "exercise for the reader".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM