简体   繁体   English

使用文件流和字典 <string, string> 在C#中使用Binary Formatter似乎无法正常工作。

[英]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. 基本上,我正在尝试将dictionary<string, string>对象序列化为文件,并稍后再加载。 I know I'm probably doing something wrong here. 我知道我可能在这里做错了。 (and yes this is an irc bot ). (是的,这是一个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: 我确实有两个父函数,即保存和加载,但编译器不喜欢我从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);
        }
    }
}

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. 首先,我不得不说,这种调试方法(将代码上传到bot并观察其行为)非常有问题,使您无法了解实际发生的情况,引发的异常等等。 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. 您尝试使用不支持的BinaryFormatter序列化Dictionary You can only use the BinaryFormatter to serialize types marked as [Serializable] , which Dictionary is not. 您只能使用BinaryFormatter序列化标记为[Serializable]类型,而Dictionary则不能。

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. 这是对.NET 1.1 / 2.0时代序列化程序的众所周知的限制,要解决此问题,您必须编写许多涉及自定义序列化的自定义代码,或者使用其他更新的序列化引擎(例如)。 NET 3.5的DataContractSerializer最初是为WCF开发的,并随WCF一起提供,它可以序列化Dictionary,但是可以序列化为XML,而不是二进制格式。

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. 首先,您的if / else情况是倒退的:对于文件不存在的情况,请调用File.Delete。

Second, the else block is missing curly brackets, so your control flow will be incorrect. 其次,else块缺少大括号,因此您的控制流程将不正确。

I will leave the corrections as the proverbial "exercise for the reader". 我将更正保留为谚语“为读者练习”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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