C#中读取含向量属性的Student类对象的技术实现问询
解决方案:从文件读取带向量属性的C# Student类对象
嘿,针对你的Student类(包含私有数组note、readonly字段、const和静态成员),我整理了几种靠谱的从文件读取对象的方案,每种都附代码示例,你可以根据自己的场景选:
方案1:使用System.Text.Json(.NET Core/.NET 5+ 原生推荐)
首先,我们需要调整Student类,确保序列化器能处理私有字段、readonly成员和构造函数:
using System; using System.Text.Json; using System.Text.Json.Serialization; // 假设基类是这样的(你需要确保基类也支持序列化) public class Person { public string Cnp { get; } public string Nume { get; } public Person(string cnp, string nume) { Cnp = cnp; Nume = nume; } } public class Student : Person { private int[] note;//分数向量 private DateTime dataInrolarii; private int nrRestante; private readonly int nrMatricol; private const string sex = "feminin"; public static int anStudiu = 3; // 标记这个构造函数用于反序列化 [JsonConstructor] public Student(string cnp, string nume, int nrMatricol, DateTime dataInrolarii, int nrRestante, int[] note) : base(cnp, nume) { this.nrMatricol = nrMatricol; this.dataInrolarii = dataInrolarii; this.nrRestante = nrRestante; this.note = note ?? Array.Empty<int>(); } // 可选:添加属性用于暴露私有字段(如果需要) public int[] Note => note; public DateTime DataInrolarii => dataInrolarii; public int NrRestante => nrRestante; public int NrMatricol => nrMatricol; }
然后是序列化到文件和读取的代码:
// 序列化学生对象到文件 var student = new Student( "1234567890123", "Maria Popescu", 12345, new DateTime(2021, 9, 1), 0, new int[] { 9, 10, 8 }); var options = new JsonSerializerOptions { IncludeFields = true, // 序列化私有字段 WriteIndented = true, // 格式化输出,方便阅读 ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor // 确保构造函数能被访问 }; string json = JsonSerializer.Serialize(student, options); File.WriteAllText("student.json", json); // 从文件读取并反序列化 string jsonFromFile = File.ReadAllText("student.json"); Student loadedStudent = JsonSerializer.Deserialize<Student>(jsonFromFile, options); // 验证读取结果 Console.WriteLine($"学生姓名:{loadedStudent.Nume}"); Console.WriteLine($"分数:{string.Join(", ", loadedStudent.Note)}");
注意:const string sex是编译时常量,不需要序列化;static int anStudiu是静态成员,默认不会被序列化(静态成员属于类而非实例),如果需要保存静态状态,得手动处理。
方案2:使用Newtonsoft.Json(Json.NET,兼容性更强)
如果是.NET Framework项目,或者需要更灵活的序列化配置,Json.NET是很好的选择:
using Newtonsoft.Json; // 同样的Student类(可以不用加[JsonConstructor],Json.NET会自动匹配构造函数参数) // 序列化到文件 var student = new Student( "1234567890123", "Maria Popescu", 12345, new DateTime(2021, 9, 1), 0, new int[] { 9, 10, 8 }); string json = JsonConvert.SerializeObject(student, Formatting.Indented); File.WriteAllText("student.json", json); // 从文件读取 string jsonFromFile = File.ReadAllText("student.json"); Student loadedStudent = JsonConvert.DeserializeObject<Student>(jsonFromFile);
Json.NET默认会处理私有字段(可以通过配置调整),并且能自动匹配构造函数参数,处理readonly字段也很顺畅。
方案3:二进制序列化(适合.NET Framework,性能高但不跨平台)
如果需要高效的二进制格式,可以用.NET的二进制序列化:
首先给Student类和基类加上[Serializable]特性:
[Serializable] public class Person { public string Cnp { get; } public string Nume { get; } public Person(string cnp, string nume) { Cnp = cnp; Nume = nume; } } [Serializable] public class Student : Person { private int[] note;//分数向量 private DateTime dataInrolarii; private int nrRestante; private readonly int nrMatricol; private const string sex = "feminin"; public static int anStudiu = 3; public Student(string cnp, string nume, int nrMatricol, DateTime dataInrolarii, int nrRestante, int[] note) : base(cnp, nume) { this.nrMatricol = nrMatricol; this.dataInrolarii = dataInrolarii; this.nrRestante = nrRestante; this.note = note ?? Array.Empty<int>(); } }
然后序列化和读取代码:
using System.IO; using System.Runtime.Serialization.Formatters.Binary; // 序列化到文件 var student = new Student( "1234567890123", "Maria Popescu", 12345, new DateTime(2021, 9, 1), 0, new int[] { 9, 10, 8 }); BinaryFormatter formatter = new BinaryFormatter(); using (FileStream stream = new FileStream("student.bin", FileMode.Create)) { formatter.Serialize(stream, student); } // 从文件读取 using (FileStream stream = new FileStream("student.bin", FileMode.Open)) { Student loadedStudent = (Student)formatter.Deserialize(stream); }
注意:二进制序列化不跨平台(比如.NET Core读取.NET Framework序列化的文件可能有问题),而且static成员和const不会被序列化。
方案4:自定义文本格式解析(比如CSV)
如果你的文件是自定义的文本格式(比如每行是学生数据,分数用逗号分隔),可以自己写解析逻辑:
假设文件内容格式如下:
CNP,Nume,NrMatricol,DataInrolarii,NrRestante,Note 1234567890123,Maria Popescu,12345,2021-09-01,0,9,10,8
解析代码:
using System.IO; using System.Linq; // 读取文件并解析 string[] lines = File.ReadAllLines("students.csv"); List<Student> students = new List<Student>(); // 跳过表头 for (int i = 1; i < lines.Length; i++) { string[] parts = lines[i].Split(','); if (parts.Length < 6) continue; string cnp = parts[0]; string nume = parts[1]; int nrMatricol = int.Parse(parts[2]); DateTime dataInrolarii = DateTime.Parse(parts[3]); int nrRestante = int.Parse(parts[4]); int[] note = parts.Skip(5).Select(int.Parse).ToArray(); Student student = new Student(cnp, nume, nrMatricol, dataInrolarii, nrRestante, note); students.Add(student); } // 使用解析后的学生对象 foreach (var s in students) { Console.WriteLine($"{s.Nume} 的分数:{string.Join(", ", s.Note)}"); }
这种方式适合需要手动控制格式的场景,但需要自己处理异常(比如格式错误、类型转换失败)。
关键注意事项
- readonly字段:反序列化时需要确保构造函数能接收该字段的值,或者序列化器支持直接赋值(比如Json.NET和System.Text.Json在配置正确时可以处理)。
- 静态/const成员:这些属于类级别的数据,不属于实例,序列化器默认不会处理它们。如果需要保存静态状态,要手动读取和写入。
- 异常处理:实际代码中要添加
try-catch块,处理文件不存在、格式错误、类型转换失败等异常。 - 基类序列化:确保Student的基类(Person)也支持序列化,否则会丢失基类的属性数据。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

