形成文件和文件夹树
Form a tree of files and folders
如何递归地从文件夹中获取所有文件夹和文件树?我需要将这棵树放入 DataTable 并从中形成一个 treeView。我在形成递归方法时遇到了一点问题,目前我只有一个不能正常工作的草稿:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private int id, parentID;
private List<TREE> tree;
public MainWindow()
{
InitializeComponent();
tree = new List<TREE>();
id = 0;
parentID = 0;
fill(@"D:\c#");
}
private List<TREE> fill(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
foreach (DirectoryInfo folder in dir.GetDirectories())
{
tree.Add(new TREE(){ID = id++, ParentID = parentID++, Name = folder.Name, Type = "Folder"});
foreach (FileInfo file in folder.GetFiles())
{
tree.Add(new TREE() { ID = id, ParentID = parentID, Name = file.Name, Type = "File" });
}
var p = folder.GetDirectories();
if (p.Length > 0)
{
dir = folder;
fill(dir.FullName);
}
}
return tree;
}
}
public class TREE
{
public int ID { get; set; }
public int ParentID {get;set;}
public string Name {get;set;}
public string Type {get;set;}
}
}
拜托,你能告诉我形成树并将树放入 DataTable 的正确方法吗?列表很好,但我需要数据表。
我试过了,但它不能正常工作:
public DataTable fill(DirectoryInfo dir)
{
DataTable dt = new DataTable("Tasks");
//dt.Columns.Add("ID");
dt.Columns.Add("ParentID");
dt.Columns.Add("Name");
dt.Columns.Add("Type");
foreach (var folder in dir.GetDirectories())
{
var row = dt.NewRow();
row["ParentID"] = folder.Parent;
row["Name"] = folder.Name;
row["Type"] = "dir";
dt.Rows.Add(row);
foreach (var file in folder.GetFiles())
{
var row2 = dt.NewRow();
row["ParentID"] = folder.Parent;
row["Name"] = file.Name;
row["Type"] = "file";
dt.Rows.Add(row2);
}
fill(folder);
}
return dt;
}
下面是我如何实现递归部分:
static class IdGenerator
{
static int _id = 1;
public static int Generate() { return _id++; }
}
class Tree
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public Tree Parent { get; set; }
public virtual ICollection<string> Files { get; set; }
public virtual ICollection<Tree> Trees { get; set; }
internal Tree ()
{
Id = IdGenerator.Generate();
Name = String.Empty;
ParentId = 0;
Parent = null;
Files = new List<string>();
Trees = new List<Tree>();
}
public override string ToString()
{
return String.Join("\n", new[] { Id + "\t" + Path.Combine(Parent != null ? Parent.Name : String.Empty, Name) }.Union(Files).Union(Trees.Select(t => t.ToString()))) + "\n";
}
public static Tree CreateTree(string path, Tree parent, string pattern)
{
try
{
var tree = new Tree
{
Parent = parent,
ParentId = parent != null ? parent.Id : 0,
Name = Path.GetFileName(path),
Files = Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Select(f => Path.GetFileName(f)).ToArray(),
};
tree.Trees = Directory.GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly).Select(d => CreateTree(d, tree, pattern)).ToArray();
return tree;
}
catch (UnauthorizedAccessException)
{ return new Tree(); }
}
}
如果我要继续这样做,我会使用 Entity Framework Code First 从 POCO Tree
生成数据库,并删除静态 IdGenerator
因为 EF 会生成这些数据库我的 ID。
编辑
但是,以下是在 DataTable 中执行此操作的方法:
class TreeDataTable : DataTable
{
public TreeDataTable()
: this("trees")
{
}
public TreeDataTable(string tableName)
: base(tableName)
{
Columns.Add("Id");
Columns.Add("Name");
Columns.Add("ParentId");
Columns.Add("Type");
}
public void AddFile(int id, string name, int parent)
{
AddRow(id, name, parent, typeof(FileInfo));
}
public void AddTree(Tree tree)
{
AddRow(tree.Id, tree.Name, tree.ParentId, typeof(DirectoryInfo));
var table = tree.ToDataTable();
foreach (var r in table.Rows.Cast<DataRow>())
AddRow(Convert.ToInt32(r["Id"]), r["Name"].ToString(), Convert.ToInt32(r["ParentId"]), Type.GetType(r["Type"].ToString()));
}
public string ToXml()
{
using (var sw = new StringWriter())
{
using (var tw = new XmlTextWriter(sw))
{
tw.Formatting = Formatting.Indented;
tw.WriteStartDocument();
tw.WriteStartElement(TableName);
((IXmlSerializable)this).WriteXml(tw);
tw.WriteEndElement();
tw.WriteEndDocument();
}
return sw.ToString();
}
}
private void AddRow(int id, string name, int parent, Type type)
{
var row = NewRow();
row["Id"] = id;
row["Name"] = name;
row["ParentId"] = parent;
row["Type"] = type.ToString();
Rows.Add(row);
}
}
并将此方法添加到 Tree
:
public DataTable ToDataTable()
{
var table = new TreeDataTable();
foreach (var f in Files)
table.AddFile(IdGenerator.Generate(), f, Id);
foreach (var t in Trees)
table.AddTree(t);
return table;
}
使用方法如下:
class Program
{
static void Main(string[] args)
{
var path = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? @"C:\Documents\Videos";
args = args.Skip(1).ToArray();
var pattern = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? "*.mp4";
var tree = Tree.CreateTree(path, null, pattern);
Console.WriteLine((tree.ToDataTable() as TreeDataTable).ToXml());
}
}
如何递归地从文件夹中获取所有文件夹和文件树?我需要将这棵树放入 DataTable 并从中形成一个 treeView。我在形成递归方法时遇到了一点问题,目前我只有一个不能正常工作的草稿:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace SWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private int id, parentID;
private List<TREE> tree;
public MainWindow()
{
InitializeComponent();
tree = new List<TREE>();
id = 0;
parentID = 0;
fill(@"D:\c#");
}
private List<TREE> fill(string path)
{
DirectoryInfo dir = new DirectoryInfo(path);
foreach (DirectoryInfo folder in dir.GetDirectories())
{
tree.Add(new TREE(){ID = id++, ParentID = parentID++, Name = folder.Name, Type = "Folder"});
foreach (FileInfo file in folder.GetFiles())
{
tree.Add(new TREE() { ID = id, ParentID = parentID, Name = file.Name, Type = "File" });
}
var p = folder.GetDirectories();
if (p.Length > 0)
{
dir = folder;
fill(dir.FullName);
}
}
return tree;
}
}
public class TREE
{
public int ID { get; set; }
public int ParentID {get;set;}
public string Name {get;set;}
public string Type {get;set;}
}
}
拜托,你能告诉我形成树并将树放入 DataTable 的正确方法吗?列表很好,但我需要数据表。
我试过了,但它不能正常工作:
public DataTable fill(DirectoryInfo dir)
{
DataTable dt = new DataTable("Tasks");
//dt.Columns.Add("ID");
dt.Columns.Add("ParentID");
dt.Columns.Add("Name");
dt.Columns.Add("Type");
foreach (var folder in dir.GetDirectories())
{
var row = dt.NewRow();
row["ParentID"] = folder.Parent;
row["Name"] = folder.Name;
row["Type"] = "dir";
dt.Rows.Add(row);
foreach (var file in folder.GetFiles())
{
var row2 = dt.NewRow();
row["ParentID"] = folder.Parent;
row["Name"] = file.Name;
row["Type"] = "file";
dt.Rows.Add(row2);
}
fill(folder);
}
return dt;
}
下面是我如何实现递归部分:
static class IdGenerator
{
static int _id = 1;
public static int Generate() { return _id++; }
}
class Tree
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public Tree Parent { get; set; }
public virtual ICollection<string> Files { get; set; }
public virtual ICollection<Tree> Trees { get; set; }
internal Tree ()
{
Id = IdGenerator.Generate();
Name = String.Empty;
ParentId = 0;
Parent = null;
Files = new List<string>();
Trees = new List<Tree>();
}
public override string ToString()
{
return String.Join("\n", new[] { Id + "\t" + Path.Combine(Parent != null ? Parent.Name : String.Empty, Name) }.Union(Files).Union(Trees.Select(t => t.ToString()))) + "\n";
}
public static Tree CreateTree(string path, Tree parent, string pattern)
{
try
{
var tree = new Tree
{
Parent = parent,
ParentId = parent != null ? parent.Id : 0,
Name = Path.GetFileName(path),
Files = Directory.GetFiles(path, pattern, SearchOption.TopDirectoryOnly).Select(f => Path.GetFileName(f)).ToArray(),
};
tree.Trees = Directory.GetDirectories(path, "*.*", SearchOption.TopDirectoryOnly).Select(d => CreateTree(d, tree, pattern)).ToArray();
return tree;
}
catch (UnauthorizedAccessException)
{ return new Tree(); }
}
}
如果我要继续这样做,我会使用 Entity Framework Code First 从 POCO Tree
生成数据库,并删除静态 IdGenerator
因为 EF 会生成这些数据库我的 ID。
编辑
但是,以下是在 DataTable 中执行此操作的方法:
class TreeDataTable : DataTable
{
public TreeDataTable()
: this("trees")
{
}
public TreeDataTable(string tableName)
: base(tableName)
{
Columns.Add("Id");
Columns.Add("Name");
Columns.Add("ParentId");
Columns.Add("Type");
}
public void AddFile(int id, string name, int parent)
{
AddRow(id, name, parent, typeof(FileInfo));
}
public void AddTree(Tree tree)
{
AddRow(tree.Id, tree.Name, tree.ParentId, typeof(DirectoryInfo));
var table = tree.ToDataTable();
foreach (var r in table.Rows.Cast<DataRow>())
AddRow(Convert.ToInt32(r["Id"]), r["Name"].ToString(), Convert.ToInt32(r["ParentId"]), Type.GetType(r["Type"].ToString()));
}
public string ToXml()
{
using (var sw = new StringWriter())
{
using (var tw = new XmlTextWriter(sw))
{
tw.Formatting = Formatting.Indented;
tw.WriteStartDocument();
tw.WriteStartElement(TableName);
((IXmlSerializable)this).WriteXml(tw);
tw.WriteEndElement();
tw.WriteEndDocument();
}
return sw.ToString();
}
}
private void AddRow(int id, string name, int parent, Type type)
{
var row = NewRow();
row["Id"] = id;
row["Name"] = name;
row["ParentId"] = parent;
row["Type"] = type.ToString();
Rows.Add(row);
}
}
并将此方法添加到 Tree
:
public DataTable ToDataTable()
{
var table = new TreeDataTable();
foreach (var f in Files)
table.AddFile(IdGenerator.Generate(), f, Id);
foreach (var t in Trees)
table.AddTree(t);
return table;
}
使用方法如下:
class Program
{
static void Main(string[] args)
{
var path = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? @"C:\Documents\Videos";
args = args.Skip(1).ToArray();
var pattern = args.FirstOrDefault(a => !String.IsNullOrEmpty(a)) ?? "*.mp4";
var tree = Tree.CreateTree(path, null, pattern);
Console.WriteLine((tree.ToDataTable() as TreeDataTable).ToXml());
}
}