C# 如何保存人类可读的文件

C# 如何保存人类可读的文件,c#,.net,xml-serialization,C#,.net,Xml Serialization,目前,我有一个应用程序,它使用二进制序列化程序将一个或两个基本类中的多个属性读写到.txt文件中 我已经在记事本中打开了.txt文件,因为它是为应用程序格式化的,所以对人眼来说不是很可读,对我来说也不是 我听说过使用XML,但我的大部分搜索似乎过于复杂 我试图保存的数据只是“Person.cs”类的集合,只不过是一个名称和地址,所有私有字符串都带有属性,并标记为可序列化 以便于个人阅读的方式保存数据的最佳方式是什么?它还使直接在文件中对应用程序的数据进行小的更改变得更容易,而不必加载、更改和保存

目前,我有一个应用程序,它使用二进制序列化程序将一个或两个基本类中的多个属性读写到.txt文件中

我已经在记事本中打开了.txt文件,因为它是为应用程序格式化的,所以对人眼来说不是很可读,对我来说也不是

我听说过使用XML,但我的大部分搜索似乎过于复杂

我试图保存的数据只是“Person.cs”类的集合,只不过是一个名称和地址,所有私有字符串都带有属性,并标记为可序列化

以便于个人阅读的方式保存数据的最佳方式是什么?它还使直接在文件中对应用程序的数据进行小的更改变得更容易,而不必加载、更改和保存数据

编辑:

我添加了当前保存和加载数据的方式,我的_userCollection正如它所建议的那样,user/n成员是一个整数

#region I/O Operations

    public bool SaveData()
    {
        try
        {
            //Open the stream using the Data.txt file
            using (Stream stream = File.Open("Data.txt", FileMode.Create))
            {
                //Create a new formatter
                BinaryFormatter bin = new BinaryFormatter();
                //Copy data in collection to the file specified earlier
                bin.Serialize(stream, _userCollection);
                bin.Serialize(stream, nMember);
                bin.Serialize(stream, nUser);
                //Close stream to release any resources used
                stream.Close();
            }
            return true;
        }
        catch (IOException ex)
        {
            throw new ArgumentException(ex.ToString());
        }
    }

    public bool LoadData()
    {
        //Check if file exsists, otherwise skip
        if (File.Exists("Data.txt"))
        {
            try
            {
                using (Stream stream = File.Open("Data.txt", FileMode.Open))
                {
                    BinaryFormatter bin = new BinaryFormatter();

                    //Copy data back into collection fields
                    _userCollection = (List<User>)bin.Deserialize(stream);
                    nMember = (int)bin.Deserialize(stream);
                    nUser = (int)bin.Deserialize(stream);
                    stream.Close();

                    //Sort data to ensure it is ordered correctly after being loaded
                    _userCollection.Sort();
                    return true;

                }
            }
            catch (IOException ex)
            {
                throw new ArgumentException(ex.ToString());
            }
        }
        else
        {
            //Console.WriteLine present for testing purposes
            Console.WriteLine("\nLoad failed, Data.txt not found");
            return false;
        }
    }
#区域I/O操作
公共bool SaveData()
{
尝试
{
//使用Data.txt文件打开流
使用(Stream=File.Open(“Data.txt”,FileMode.Create))
{
//创建一个新的格式化程序
BinaryFormatter bin=新的BinaryFormatter();
//将集合中的数据复制到前面指定的文件
序列化(流,_userCollection);
序列化(流,n成员);
序列化(流,用户);
//关闭流以释放所使用的任何资源
stream.Close();
}
返回true;
}
捕获(IOEX异常)
{
抛出新ArgumentException(例如ToString());
}
}
公共bool LoadData()
{
//检查文件是否存在,否则跳过
如果(File.Exists(“Data.txt”))
{
尝试
{
使用(Stream=File.Open(“Data.txt”,FileMode.Open))
{
BinaryFormatter bin=新的BinaryFormatter();
//将数据复制回集合字段
_userCollection=(列表)bin.Deserialize(流);
nMember=(int)bin.反序列化(流);
用户=(int)bin.反序列化(流);
stream.Close();
//对数据进行排序,以确保加载后数据的顺序正确
_userCollection.Sort();
返回true;
}
}
捕获(IOEX异常)
{
抛出新ArgumentException(例如ToString());
}
}
其他的
{
//Console.WriteLine用于测试目的
Console.WriteLine(“\n加载失败,找不到Data.txt”);
返回false;
}
}

您可以实现自己的
PersonWriter
,它将
StreamWriter
作为构造函数参数,并具有
Write
方法,该方法将
IList
作为输入,以解析出一个好的文本表示

例如:

public class PersonsWriter : IDisposable
{
    private StreamWriter _wr;

    public PersonsWriter(IList<Person> persons, StreamWriter writer)
    {
        this._wr = writer;
    }

    public void Write(IList<Persons> people) {
        foreach(Person dude in people)
        {
            _wr.Write(@"{0} {1}\n{2}\n{3} {4}\n\n",
                dude.FirstName,
                dude.LastName,
                dude.StreetAddress,
                dude.ZipCode,
                dude.City);
        }
    }

    public void Dispose()
    {
        _wr.Flush();
        _wr.Dispose();
    }
}
公共类PersonWriter:IDisposable
{
私人流动写手(西铁);
公共人物作家(IList人物、StreamWriter作家)
{
这个._wr=编写器;
}
公共无效写入(IList人员){
foreach(人物中的人物)
{
_Write(@“{0}{1}\n{2}\n{3}{4}\n\n”,
都德,名字,
都德,姓,
都德,街道地址,
都德,ZipCode,
都德,城市);
}
}
公共空间处置()
{
_wr.Flush();
_wr.Dispose();
}
}

使用XmlSerializer其实并不复杂。查看此MSDN页面以获取示例:

用XMLSerializer替换BinaryFormatter并运行相同的代码

您需要做的唯一更改是BinaryFormatter采用空构造函数,而对于XMLSerializer,您需要在构造函数中声明类型:

XmlSerializer serializer = new XmlSerializer(typeof(Person));
试试


它将对象序列化为XML,并且非常易于使用,如果您希望在Windows环境中在人机可读性之间取得良好的折衷,可以编写CSV读写器

也会加载到Excel中

这里有一个关于它的讨论:

编辑

那是一篇C#文章。。。它只是在URL中有一个令人困惑的“C”。

是人类可读标记的另一个选项,也很容易解析。c#以及几乎所有其他流行语言都有可用的库。下面是yaml的示例:

invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046

我真的认为您应该使用XML(查看DataContractSerializer)。没那么复杂。您甚至可以用XMLSerializer替换BinarySerializer,然后继续

但是,如果您仍然不想这样做,可以编写一个带分隔符的文本文件。然后您必须编写自己的reader方法(尽管它几乎可以使用split方法)

//在Person类中:
公共重写字符串ToString()
{
List propValues=新列表();
//获取类型。
Type t=this.GetType();
//循环浏览属性。
foreach(t.GetProperties()中的PropertyInfo p)
{
add(“{0}:={1}”,p.Name,p.GetValue(o,null));
}
返回字符串.Join(“,”.propValues.ToArray())
}
使用(System.IO.TextWriter tw=new System.IO.StreamWriter(“output.txt”))
{
tw.WriteLine(person.ToString());
}

坦率地说,作为一个人,我觉得XML不是那么可读。事实上,它并不是为人类设计的

如果您想要一种人类可读的格式,那么您必须构建它

比如说,您有一个Person类,它的属性包括名字、姓氏和SSN。创建您的文件,并让它写出3行,描述为t
//Inside the Person class:
public override string ToString()
{
    List<String> propValues = new List<String>();

    // Get the type.
    Type t = this.GetType();

    // Cycle through the properties.
    foreach (PropertyInfo p in t.GetProperties())
    {
        propValues.add("{0}:={1}", p.Name, p.GetValue(o, null));
    }

    return String.Join(",". propValues.ToArray())
}

using (System.IO.TextWriter tw = new System.IO.StreamWriter("output.txt"))
{
    tw.WriteLine(person.ToString());
}
First Name-------Stephen
Last Name -------Wrighton
SSN -------------XXX-XX-XXXX