使用文件流和dictionary在c#中使用二进制格式化器似乎不能正常工作
本文关键字:string 不能 常工作 工作 格式化 dictionary 文件 二进制 | 更新日期: 2023-09-27 18:06:12
基本上我试图序列化一个dictionary<string, string>
对象到一个文件,并加载它回来以后。我知道我可能做错了什么。(是的,这是一个irc bot
)。问题是字典的全部内容没有保存到文件中,在我的调试窗口中,我得到了"没有保存"的文本,这意味着它可能没有。它有时也会崩溃(离开聊天然后返回)关于这件事,我能说的就这些了。如果我做错了什么,我认为这可能与我的嵌套语句或文件处理程序没有以正确的方式处理有关。
我确实有两个父函数,保存和加载,但编译器不喜欢我从IRCBOT
类内调用它们下面是完整的代码:
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);
}
}
}
首先,我必须说这种调试方法(将代码上传到bot并观察其行为)非常有问题,使您无法了解实际发生了什么,抛出了什么异常等等。是否有一种方法可以将调试器附加到进程,或者保存带有更多异常详细信息的日志?
无论如何,在这种情况下,通灵调试应该足以帮助我们。您正在尝试使用BinaryFormatter
序列化Dictionary
,这是不支持的。您只能使用BinaryFormatter
来序列化标记为[Serializable]
的类型,而Dictionary
不能。
这是。net 1.1/2.0时代序列化器的一个众所周知的限制,为了解决这个问题,你必须编写大量涉及自定义序列化的自定义代码,或者使用不同的、更新的序列化引擎,比如。net 3.5的DataContractSerializer
,它最初是为WCF开发并随WCF一起发布的,它可以序列化字典,但只能序列化成XML,而不能序列化成二进制格式。
你的问题在这里:
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。如果文件不存在,则删除。
第二,else块缺少花括号,所以你的控制流将是不正确的。
我将把更正作为众所周知的"读者练习"。