在带有二进制格式化程序的C#中使用文件流和字典<string,string =“”>似乎无法正常工作。</string,>

时间:2014-05-31 03:31:23

标签: c# serialization dictionary filestream

基本上我试图将dictionary<string, string>对象序列化为文件,然后再将其加载回来。我知道我在这里可能做错了什么。 (是的,这是一个irc bot)。问题是字典的全部内容没有保存到文件中,而在我的调试窗口中,我没有保存&#34;没有保存&#34;文字,这意味着它可能没有。 它有时也会崩溃(离开聊天然后返回) 这就是我能真正说出来的事情..如果我做错了我认为这可能与我的嵌套语句或文件处理程序没有处理有关以正确的方式。

我有两个父函数,保存和加载,但编译器不喜欢我在IRCBOT CLASS中调用它们 这是完整的代码:

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);
        }
    }
}

2 个答案:

答案 0 :(得分:0)

首先,我不得不说这种调试方法(将代码上传到你的机器人并观察它的行为)是非常有问题的,让你没有关于实际发生的事情的信息,抛出了什么异常等等。有没有办法将调试器附加到进程,或者保存包含更多异常详细信息的日志?

无论如何,在这种情况下,通灵调试应该足以帮助我们。您尝试使用不受支持的Dictionary序列化BinaryFormatter。您只能使用BinaryFormatter序列化标记为[Serializable]的类型,Dictionary不是。

这是对.NET 1.1 / 2.0时代序列化程序的众所周知的限制,为了解决这个问题,您必须编写大量涉及自定义序列化的自定义代码,或者使用不同的更新的序列化引擎,例如.NET 3.5&#39; DataContractSerializer,最初为WCF开发并随WCF一起提供,它可以序列化字典,但是可以将其转换为XML,而不是二进制格式。

答案 1 :(得分:0)

你的问题在于:

                    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...");
                    }

首先,你的if / else案例是倒退的:你在文件不存在的情况下调用File.Delete。

其次,else块缺少大括号,因此您的控制流将不正确。

我将把更正作为谚语&#34;练习给读者&#34;。