关于生成树型结构的文件关系图的算法
在很多时候我们都希望生成如果下样式的文件关系图:
这个是由DOS命令生成的,但在图形界面的今天,很多人不愿意去依赖单纯的命令,我下面就讲述一下如何生成一个类似的关系,并生成文本文件.
界面如上.
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Threading;
namespace 文件名输出
{
/// <summary>
/// Form1 的摘要说明。
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnTarget;
private System.Windows.Forms.TextBox txtPath;
private System.Windows.Forms.Button btnOk;
private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
private System.Windows.Forms.SaveFileDialog saveFileDialog1;
private string Path;
private StreamWriter sw;
private Thread thread;
private System.Windows.Forms.Label lblState;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
private void Init()
{
}
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
Init();
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.btnTarget = new System.Windows.Forms.Button();
this.txtPath = new System.Windows.Forms.TextBox();
this.btnOk = new System.Windows.Forms.Button();
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
this.saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();
this.lblState = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// btnTarget
//
this.btnTarget.Location = new System.Drawing.Point(264, 16);
this.btnTarget.Name = "btnTarget";
this.btnTarget.Size = new System.Drawing.Size(96, 23);
this.btnTarget.TabIndex = 0;
this.btnTarget.Text = "目标文件夹...";
this.btnTarget.Click += new System.EventHandler(this.btnTarget_Click);
//
// txtPath
//
this.txtPath.Location = new System.Drawing.Point(8, 16);
this.txtPath.Name = "txtPath";
this.txtPath.Size = new System.Drawing.Size(248, 21);
this.txtPath.TabIndex = 1;
this.txtPath.Text = "";
//
// btnOk
//
this.btnOk.Location = new System.Drawing.Point(264, 48);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(96, 23);
this.btnOk.TabIndex = 2;
this.btnOk.Text = "输出";
this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
//
// saveFileDialog1
//
this.saveFileDialog1.DefaultExt = "txt";
this.saveFileDialog1.Filter = "文本文件|*.txt|所有文件|*.*";
//
// lblState
//
this.lblState.Location = new System.Drawing.Point(16, 48);
this.lblState.Name = "lblState";
this.lblState.Size = new System.Drawing.Size(152, 23);
this.lblState.TabIndex = 3;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(368, 83);
this.Controls.Add(this.lblState);
this.Controls.Add(this.btnOk);
this.Controls.Add(this.txtPath);
this.Controls.Add(this.btnTarget);
this.Name = "Form1";
this.Text = "文件名输出";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
//点 目标文件夹 按钮后打开FolderBrowserDialog 对话筐
private void btnTarget_Click(object sender, System.EventArgs e)
{
if(this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
this.txtPath.Text = this.folderBrowserDialog1.SelectedPath;
}
//点输出按钮后的事件处理
private void btnOk_Click(object sender, System.EventArgs e)
{
try
{
//打开保存对话筐,设置文件关系文本文件的保存位置
if(this.saveFileDialog1.ShowDialog() == DialogResult.OK)
{
//在一个新线程中执行Search函数
this.thread = new Thread(new ThreadStart(this.Search));
this.thread.Start();
}
}
catch(Exception ex)
{
this.lblState.Text = "错误,请重试!";
MessageBox.Show(ex.Message);
}
}
//下面我们来重点讲一下如何遍历目录,如何生成图一的那种表现形式:
//SearchFile函数有2个参数,RootPath为查找位置,Indent控制输出的字符前面有多少空格,既缩进
//遍历用的是递归,深度越大字符前面的空格也就越多,并且要判断是目录还是文件,是目录的话要多加一
//个’ │’.
//每个文件的前面都有一个──
//│ ├─中国古典文学名著全书
//│ └─中共往事沉浮
//├─中国文学(一)
//│ ├─鲁迅全集
//│ ├─陈香梅文集
//│ ├─金庸全集
//│ ├─路遥文集
//│ ├─路翎文集
//│ ├─苏雪林文集
//│ ├─苏童文集
//│ ├─老舍文集
//│ ├─琼瑶全集
//│ ├─王朔文集
//│ ├─曾卓文文集
//│ ├─张爱玲文集
//│ ├─古龙全集
//│ ├─冰心全集
//│ ├─余华文集
//│ └─三毛散文全编
//└─linux
private void Search()
{
this.lblState.Text = "正在输入..."; //在界面上显示状态
this.Path = this.saveFileDialog1.FileName;
this.sw = new StreamWriter(this.Path,false);
//在文件第一行写入一个标题
sw.WriteLine(this.txtPath.Text + "-------------------"); this.SearchFile(this.txtPath.Text," │");
this.sw.Close();
this.lblState.Text = "输出完毕!";
}
private void SearchFile(string RootPath,string Indent)
{
DirectoryInfo di = new DirectoryInfo(RootPath);
FileInfo[] f = di.GetFiles();
//迭代目录中的所有文件
foreach(FileInfo myFile in f)
{
sw.WriteLine(Indent);
//在文件名前+上一个’ ──’;
sw.WriteLine(Indent + "──" + myFile.Name);
}
DirectoryInfo[] d = di.GetDirectories();
//遍历目录中所有的子目录
foreach(DirectoryInfo myDir in d)
{
sw.WriteLine(Indent);
//在所有文件名前+上一个’ ──’;
sw.WriteLine(Indent + "──" + myDir.FullName);
//递归调用SearchFile,并且第二个参数要比以前多了一个" │",因为他是下一级//目录,应该比上一级多缩进一点
this.SearchFile(myDir.FullName,Indent + " │");
}
}
}
}
整个程序就是这样,其实很简单,不过在文件名显示的缩进上要琢磨一下,这个程序,有一个地方不好,在文件的结尾并没有以
│ ├─bindconf
│ └─authconfig
├─21日学会 Linux
│ ├─UNIX
│ └─LINUX
└─LINUX内核源代码情景分析
这种形式结尾,而都是直接 “|” 收工,这个问题我一直都没有好的方法来解决,如果大家有好的算法还请给出来.