【问题标题】:Saving FileSystemInfo Array to File将 FileSystemInfo 数组保存到文件
【发布时间】:2015-08-23 11:17:46
【问题描述】:

我正在尝试保存一组 FileInfo 和 DirectoryInfo 对象以用作日志文件。目标是在某个时间点捕获目录(和子目录)的图像以供以后比较。我目前正在使用这个类来存储信息:

public class myFSInfo
{
    public FileSystemInfo Dir;
    public string RelativePath;
    public string BaseDirectory;
    public myFSInfo(FileSystemInfo dir, string basedir)
    {
        Dir = dir;
        BaseDirectory = basedir;
        RelativePath = Dir.FullName.Substring(basedir.Length + (basedir.Last() == '\\' ? 1 : 2));
    }
    private myFSInfo() { }
    /// <summary>
    /// Copies a FileInfo or DirectoryInfo object to the specified path, creating folders and overwriting if necessary.
    /// </summary>
    /// <param name="path"></param>
    public void CopyTo(string path)
    {
        if (Dir is FileInfo)
        {
            var f = (FileInfo)Dir;
            Directory.CreateDirectory(path.Substring(0,path.LastIndexOf("\\")));
            f.CopyTo(path,true);
        }
        else if (Dir is DirectoryInfo) Directory.CreateDirectory(path);
    }
}

我尝试过 XML 和 Binary 序列化我的课程,但没有成功。我还尝试创建一个不包含实际 FileInfo 但仅包含选定属性的新类:

public class myFSModInfo
{
    public Type Type;
    public string BaseDirectory;
    public string RelativePath;
    public string FullName;
    public DateTime DateModified;
    public DateTime DateCreated;
    public myFSModInfo(FileSystemInfo dir, string basedir)
    {
        Type = dir.GetType();
        BaseDirectory = basedir;
        RelativePath = dir.FullName.Substring(basedir.Length + (basedir.Last() == '\\' ? 1 : 2));
        FullName = dir.FullName;
        DateModified = dir.LastWriteTime;
        DateCreated = dir.CreationTime;
    }
    private myFSModInfo() { }
    /// <summary>
    /// Copies a FileInfo or DirectoryInfo object to the specified path, creating folders and overwriting if necessary.
    /// </summary>
    /// <param name="path"></param>
    public void CopyTo(string path)
    {
        if (Type == typeof(FileInfo))
        {
            Directory.CreateDirectory(path.Substring(0, path.LastIndexOf("\\")));
            File.Copy(FullName,path, true);
        }
        else if (Type == typeof(DirectoryInfo)) Directory.CreateDirectory(path);
    }
    public void Delete() 
    {
        if (Type == typeof(FileInfo)) File.Delete(FullName);
        else if (Type == typeof(DirectoryInfo)) Directory.Delete(FullName);
    }
}

我也没有运气序列化这个。我可以列出我在各种尝试中遇到的错误,但首先选择最佳方法可能更容易。这是我的序列化代码:

public void SaveLog(string savepath, string dirpath)
    {
        var dirf = new myFSModInfo[1][];
        string[] patharr = {dirpath}; 
        GetFSInfo(patharr, dirf);

        var mySerializer = new System.Xml.Serialization.XmlSerializer(typeof(myFSModInfo[]));
        var myWriter = new StreamWriter(savepath);
        mySerializer.Serialize(myWriter, dirf[0]);
        myWriter.Close();

        /*var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();   
        FileStream fs = new FileStream(savepath, FileMode.Create, FileAccess.Write);   
        bf.Serialize(fs, dirf[0]);  */
    }

【问题讨论】:

  • 认为你只能序列化属性,不能序列化变量。
  • 您能否就您遇到的问题提供更具体的细节?
  • 您是否将类声明为可序列化的? [可序列化]
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 谢谢约翰。 Sorceri - 除了我发布的代码之外,我没有做任何事情。如果将其声明为 Serializable 可以解决我的问题,您能告诉我语法吗? Octopoid - 我遇到的大多数问题都是序列化程序失败,因为类不包含 0 参数构造函数。我也遇到了 Type 是受保护变量的问题。如果有我应该关注的特定路线,我可以发布确切的错误消息。

标签: c# arrays xml file serialization


【解决方案1】:

FileSystemInfo 不可序列化,因为它不是simple type。 FileInfo 不可序列化,因为它没有空的default constructor

因此,如果您想保存该信息,您必须使用简单类型构建您自己的类,将来自 FileInfo 或 FileSystemInfo 的信息包装起来。

[Serializable]
public class MyFileInfo
{
    public string Name { get; set; }

    public long Length { get; set;}

    /// <summary>
    /// An empty ctor is needed for serialization.
    /// </summary>
    public MyFileInfo(){
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="test.MyFileInfo"/> class.
    /// </summary>
    /// <param name="fileInfo">File info.</param>
    public MyFileInfo(string path)
    {
        FileInfo fileInfo = new FileInfo (path);
        this.Length = fileInfo.Length;
        this.Name = fileInfo.Name;
        // TODO: add and initilize other members
    }
}

示例用法:

List<MyFileInfo> list = new List<MyFileInfo> ();

foreach (string entry in Directory.GetFiles(@"c:\temp"))
{
    list.Add (new MyFileInfo (entry));
}

XmlSerializer xsSubmit = new XmlSerializer(typeof(List<MyFileInfo>));
StringWriter sww = new StringWriter();
XmlWriter writer = XmlWriter.Create(sww);
xsSubmit.Serialize(writer, list);

Console.WriteLine (sww.ToString());

【讨论】:

  • 谢谢 ec8or。阅读您的回复后,我意识到我错误地重复了第一个代码块,而不是发布我的第二堂课尝试。我现在已经解决了。它符合您的建议,但我收到此错误:“System.InvalidOperationException: System.RuntimeType 由于其保护级别而无法访问。只能处理公共类型。”
  • 某些访问修饰符可能是错误的。确保您要序列化的类是公开的。如果它有复杂的属性,它们也必须有一个 publiv 可见类型。如果要忽略某些属性,则必须使用 [XmlIgnore] -Attribute。
  • 您可以在上面的第二个代码块中看到我的课程。我想我都公开了。我不想忽略任何属性,因为我只在这个类中包含了我需要的属性。在我的第一堂课中,我包含了一个 FileSystemInfo 对象,它具有我可以忽略的属性,但 XMLserializer 不喜欢 FileInfo。我添加了 Serializeable 标签,但仍然没有运气。知道问题是什么吗?
  • 这里的问题是Type。它不可序列化,因为System.RuntimeType is inaccessible due to its protection level.。它是一种内部 CLR 类型。另外它不是一个简单的类型。明白了吗?
  • 那么你为什么需要那个类型呢?您还可以创建一个名为 IsFile 的 bool 属性作为 workarround!?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 2015-05-30
  • 2016-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多