将 FileSystemInfo 数组保存到文件

Saving FileSystemInfo Array to File

提问人:Kalev Maricq 提问时间:6/9/2015 最后编辑:Kalev Maricq 更新时间:6/10/2015 访问量:927

问:

我正在尝试保存 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]);  */
    }
C# 数组 XML 文件 序列化

评论

4赞 Chuck Savage 6/9/2015
认为您只能序列化属性,而不能序列化变量。
0赞 Octopoid 6/9/2015
你能提供一些关于你遇到的问题的更具体的细节吗?
1赞 Sorceri 6/9/2015
您是否将该类声明为可序列化?[可序列化]
0赞 John Saunders 6/9/2015
我已经编辑了你的标题。请参阅“问题是否应该在标题中包含”标签“,其中的共识是”不,他们不应该”。
0赞 Kalev Maricq 6/10/2015
谢谢约翰。Sorceri - 除了我发布的代码之外,我没有做任何事情。如果将其声明为 Serializable 可以解决我的问题,您能告诉我语法吗?Octopoid - 我发现的大多数问题都是序列化程序的失败,因为类不包含 0 参数构造函数。我也遇到了类型受保护变量的问题。如果有我应该关注的特定路线,我可以发布确切的错误消息。

答:

5赞 devmb 6/9/2015 #1

FileSystemInfo 不可序列化,因为它不是简单类型。FileInfo 不可序列化,因为它没有空的默认构造函数

因此,如果要保存该信息,则必须使用简单类型构建自己的类,这些类型包装来自 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());

评论

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