C# 中的序列化异常
SerializationException in C#
我在 CSharp 中的代码中有以下异常:
The serializer doesnt take count the serialization of generic types:
System.Collections.Generic.SortedSet`
这是我的有问题的代码(在 class FileStreamer 中):
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
下面是我在项目中使用的class:
主要class:
class Program
{
public static void Main(string[] args)
{
GestAuthentification ga = new Authentification () ;
try
{
ga.addUser("bob","123");
ga.removeUser("bob");
ga.removeUser("bob");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
}
try
{
ga.addUser("bob","123");
ga.authentify("bob","123");
ga.authentify("bob","456");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
}
//Until here it works
try
{
ga.save("users.txt");
GestAuthentification gb = new Authentification();
gb.load("users.txt");
gb.authentify("bob","123");
Console.WriteLine("Test sauvegarde/chargement réussi !");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est n'est plus connu. Problème de sauvegarde/chargement.");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !Problème de sauvegarde/chargement.");
} catch (IOException e) {
Console.WriteLine(e);
}
}
}
Authentification.cs
[Serializable]
public class Authentification: GestAuthentification
{
private SortedSet<User> userset;
public Authentification()
{
this.userset = new SortedSet<User>();
}
public void addUser(String login, String pass)
{
if (userset.Count() == 0)
{
User usr0 = new User(login, pass);
userset.Add(usr0);
Console.WriteLine(usr0._login + " a été ajoute");
return;
}
else
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
throw new UserExists(u);
}
}
User usr = new User(login, pass);
userset.Add(usr);
Console.WriteLine(usr._login + " a été ajoute");
}
}
public void removeUser(String login)
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
userset.Remove(u);
Console.WriteLine(u._login + " a été retiré.");
return;
}
}
User usr = new User(login,"");
throw new UserUnknown(usr);
}
public void authentify(String login, String Pass)
{
foreach (User u in userset)
{
if (u._login.Equals(login)&&u._password.Equals(Pass))
{
Console.WriteLine(u._login + " a été authenthifié.");
return;
}
else if((u._login.Equals(login))&&(u._password.Equals(Pass)==false))
{
throw new WrongPassword(u);
}
}
User usr = new User(login, "");
throw new UserUnknown(usr);
}
public void load(String path)
{
FileStreamer<User>.SoapLoad(path);
}
public void save(String path)
{
FileStreamer<User>.SoapSave(userset, path);
}
}
FileStreamer.cs
public class FileStreamer<T>
{
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
FileStream stream = File.OpenRead(filename);
SoapFormatter formatter = new SoapFormatter();
SortedSet<T> set = (SortedSet<T>)formatter.Deserialize(stream);
stream.Close();
return set;
}
}
User.cs
public class User: IComparable<User>
{
private string login;
private string password;
public string _login
{
get{return login;}
set {login=value;}
}
public string _password
{
get { return password; }
set { password = value; }
}
public User(string l, string p)
{
login = l;
password = p;
}
public int CompareTo(User u)
{
if(login.CompareTo(u._login)>0)
{
return 1;
}
else if(login.CompareTo(u._login)==0)
{
return 0;
}
else
{
return -1;
}
}
}
那么我项目中序列化的问题在哪里,如何纠正?
谢谢。
您可能会在现代 .Net 上下文中使用 SoapFormatter
遇到许多问题。来自 docs:
Beginning with the .NET Framework 2.0, this class is obsolete. Use BinaryFormatter instead.
也就是说,如您所见,SoapFormatter
不支持泛型。但是,它确实支持 arrays,数组早在 .Net 1 就已存在。因此您可以将 SortedSet<T>
序列化为数组:
public class FileStreamer<T>
{
static void SoapSave(SortedSet<T> set, Stream stream)
{
var formatter = new SoapFormatter();
formatter.Serialize(stream, set.ToArray());
}
public static SortedSet<T> SoapLoad(Stream stream)
{
var formatter = new SoapFormatter();
var array = (T [])formatter.Deserialize(stream);
return new SortedSet<T>(array);
}
public static bool SoapSave(SortedSet<T> set, string filename)
{
using (var stream = File.Create(filename))
{
SoapSave(set, stream);
}
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
using (var stream = File.OpenRead(filename))
{
return SoapLoad(stream);
}
}
}
注意 SoapFormatter
还要求您将 User
class 标记为 [Serializable]
:
[Serializable]
public class User : IComparable<User>
{
// Remainder of the class unchanged.
}
我在 CSharp 中的代码中有以下异常:
The serializer doesnt take count the serialization of generic types: System.Collections.Generic.SortedSet`
这是我的有问题的代码(在 class FileStreamer 中):
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
下面是我在项目中使用的class:
主要class:
class Program
{
public static void Main(string[] args)
{
GestAuthentification ga = new Authentification () ;
try
{
ga.addUser("bob","123");
ga.removeUser("bob");
ga.removeUser("bob");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
}
try
{
ga.addUser("bob","123");
ga.authentify("bob","123");
ga.authentify("bob","456");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !");
} catch (UserExists e) {
Console.WriteLine(e.Login +" est déjà dans le système! on ne peut le recréer.");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est inconnu du système! on ne peut le retirer.");
}
//Until here it works
try
{
ga.save("users.txt");
GestAuthentification gb = new Authentification();
gb.load("users.txt");
gb.authentify("bob","123");
Console.WriteLine("Test sauvegarde/chargement réussi !");
} catch (UserUnknown e) {
Console.WriteLine(e.Login +" est n'est plus connu. Problème de sauvegarde/chargement.");
} catch (WrongPassword e) {
Console.WriteLine(e.Login+" s'est trompé de password !Problème de sauvegarde/chargement.");
} catch (IOException e) {
Console.WriteLine(e);
}
}
}
Authentification.cs
[Serializable]
public class Authentification: GestAuthentification
{
private SortedSet<User> userset;
public Authentification()
{
this.userset = new SortedSet<User>();
}
public void addUser(String login, String pass)
{
if (userset.Count() == 0)
{
User usr0 = new User(login, pass);
userset.Add(usr0);
Console.WriteLine(usr0._login + " a été ajoute");
return;
}
else
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
throw new UserExists(u);
}
}
User usr = new User(login, pass);
userset.Add(usr);
Console.WriteLine(usr._login + " a été ajoute");
}
}
public void removeUser(String login)
{
foreach (User u in userset)
{
if (u._login.Equals(login))
{
userset.Remove(u);
Console.WriteLine(u._login + " a été retiré.");
return;
}
}
User usr = new User(login,"");
throw new UserUnknown(usr);
}
public void authentify(String login, String Pass)
{
foreach (User u in userset)
{
if (u._login.Equals(login)&&u._password.Equals(Pass))
{
Console.WriteLine(u._login + " a été authenthifié.");
return;
}
else if((u._login.Equals(login))&&(u._password.Equals(Pass)==false))
{
throw new WrongPassword(u);
}
}
User usr = new User(login, "");
throw new UserUnknown(usr);
}
public void load(String path)
{
FileStreamer<User>.SoapLoad(path);
}
public void save(String path)
{
FileStreamer<User>.SoapSave(userset, path);
}
}
FileStreamer.cs
public class FileStreamer<T>
{
public static bool SoapSave(SortedSet<T> set, string filename)
{
FileStream stream = File.Create(filename);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(stream, set);
stream.Close();
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
FileStream stream = File.OpenRead(filename);
SoapFormatter formatter = new SoapFormatter();
SortedSet<T> set = (SortedSet<T>)formatter.Deserialize(stream);
stream.Close();
return set;
}
}
User.cs
public class User: IComparable<User>
{
private string login;
private string password;
public string _login
{
get{return login;}
set {login=value;}
}
public string _password
{
get { return password; }
set { password = value; }
}
public User(string l, string p)
{
login = l;
password = p;
}
public int CompareTo(User u)
{
if(login.CompareTo(u._login)>0)
{
return 1;
}
else if(login.CompareTo(u._login)==0)
{
return 0;
}
else
{
return -1;
}
}
}
那么我项目中序列化的问题在哪里,如何纠正?
谢谢。
您可能会在现代 .Net 上下文中使用 SoapFormatter
遇到许多问题。来自 docs:
Beginning with the .NET Framework 2.0, this class is obsolete. Use BinaryFormatter instead.
也就是说,如您所见,SoapFormatter
不支持泛型。但是,它确实支持 arrays,数组早在 .Net 1 就已存在。因此您可以将 SortedSet<T>
序列化为数组:
public class FileStreamer<T>
{
static void SoapSave(SortedSet<T> set, Stream stream)
{
var formatter = new SoapFormatter();
formatter.Serialize(stream, set.ToArray());
}
public static SortedSet<T> SoapLoad(Stream stream)
{
var formatter = new SoapFormatter();
var array = (T [])formatter.Deserialize(stream);
return new SortedSet<T>(array);
}
public static bool SoapSave(SortedSet<T> set, string filename)
{
using (var stream = File.Create(filename))
{
SoapSave(set, stream);
}
return true;
}
public static SortedSet<T> SoapLoad(string filename)
{
using (var stream = File.OpenRead(filename))
{
return SoapLoad(stream);
}
}
}
注意 SoapFormatter
还要求您将 User
class 标记为 [Serializable]
:
[Serializable]
public class User : IComparable<User>
{
// Remainder of the class unchanged.
}