【C#】递归遍历一个文件夹里的所有文件

711 阅读4分钟

前言:

公司最近整理文档,老板安排我一个任务将接近1000个的文档的名称提取出来放在Excel表格中,只需要.doc或.docx的文件

这么多个文件可能不能一个一个复制粘贴啊,快速的方法就是写个脚本

分析

于是,我开始分析这些文件,文件夹里面有文件,文件夹里面还有文件夹,于是我想到递归

文件名称的格式是这样的,类似这样

1001001001_A_XXX承认书

  • 1001001001,表示编号
  • A,表示版本号,可能是A,B,C,依次类推
  • XXX承认书,表示名称

很多文件名称就是上面的格式,但是有很多文件名称没有完全按照上面的格式来,毕竟有很多文件,还有不同文件有不同人创建的

于是我就要考虑很多种情况了,

继续分析文件名

有些文件名是这样的

1001001001 XXX承认书,直接没有版本号,(没有版本号的默认A)

也有些文件名是这样的

1001001001A XXX承认书

也有些文件名是这样的

1001001001XXX承认书 (直接是编号+名称)

还有一个问题就是有些编号是9位的,大多都是10位的

且编号与版本号,版本号与名称的分隔符不一定都是“_”,也有“-”和“ ”

实现

先创建一个Model来存储内容

class Model
{
    public string Num { get; set; }//编号
    public string Ver { get; set; }//版本号
    public string Name { get; set; }//名称
}

传入一个路径,用递归遍历文件夹的所有文件

/// <summary>
/// 获取文件夹
/// </summary>
/// <param name="path"></param>
private void GetDire(string path)
{
    GetFiles(path);

    string[] sonDires = Directory.GetDirectories(path);
    if (sonDires.Length > 0)
    {
        foreach (string dire in sonDires)
        {
            GetDire(dire);
        }
    }
}

获取文件夹下的所有文件

/// <summary>
/// 获取文件夹下的所有文件
/// </summary>
private void GetFiles(string path)
{
    string[] files = Directory.GetFiles(path);

    foreach (string file in files)
    {
        //获取文件名
        string fileName = file.Substring(file.LastIndexOf("\\") + 1);
        GetFile(path, fileName);
    }
}

创建存储数据

Model model;
List<Model> list = new List<Model>();

解析

接下来就是解析文件了

根据上面的分享需要用到几个判断方法

分别判断字符是否汉字,是否数字,是否字母,判断分隔符是否" ","-","_"

/// <summary>
/// 判断是否汉字
/// </summary>
private bool IsChinese(string value)
{
    Regex rg = new Regex("^[\u4e00-\u9fa5]$");
    return rg.IsMatch(value);
}

/// <summary>
/// 判断是否数字
/// </summary>
private bool IsNumber(string value)
{
    Regex rg = new Regex("^[0-9]$");
    return rg.IsMatch(value);
}

/// <summary>
/// 判断是否字母
/// </summary>
private bool IsWord(string value)
{
    Regex rg = new Regex("^[a-zA-Z]$");
    return rg.IsMatch(value);
}

/// <summary>
/// 判断字符" ","-","_"
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private bool IsSpace(string value)
{
    return (value.Contains(" ") || value.Contains("-") || value.Contains("_"));
}

解析获取文件

/// <summary>
/// 获取特定的文件
/// </summary>
private void GetFile(string path, string fileName)
{
    //不是.doc和.docx的文件不添加
    if (Path.GetExtension(fileName) != ".doc" && Path.GetExtension(fileName) != ".docx")
    {
        return;
    }
    //特殊文件不添加
    if (fileName.StartsWith("~") || fileName.Contains("xxxxxxxx"))
    {
        return;
    }

    //文件名第一个字符不为数字,不添加
    if (!IsNumber(fileName.Substring(0, 1)))
    {
        return;
    }

    //提取名称,不含扩展名
    fileName = fileName.Substring(0, fileName.LastIndexOf("."));

    model = new Model();

    #region  编号

    string Num10 = fileName.Substring(0, 10);

    int numLastIndex = 10;//编号的最后一个在名称中的索引

    //10位编号
    if (long.TryParse(Num10, out long num))
    {
        model.Num = Num10;
    }
    else//9位编号
    {
        string Num9 = fileName.Substring(0, 9);

        if (long.TryParse(Num9, out long num2))
        {
            model.Num = Num9;
        }

        numLastIndex = 9;
    }

    #endregion


    string numNext = fileName.Substring(numLastIndex, 1);//编号的下一个字符
    string verNext = fileName.Substring(numLastIndex + 2, 1);//版本的下一个字符

    //编号后且名称前是" ","-","_"
    if (IsSpace(numNext) && IsSpace(verNext))//类似 1001001001-A XXX承认书
    {
        model.Ver = fileName.Substring(numLastIndex + 1, 1);
        int nameStartIndex = numLastIndex + 3;
        model.Name = fileName.Substring(nameStartIndex, fileName.Length - nameStartIndex);
    }
    //编号后是" ","-","_",名称前不是,则没有版本号
    else if (IsSpace(numNext) && !IsSpace(verNext))//类似 1001001001 XXX承认书
    {
        int nameStartIndex = numLastIndex + 1;
        model.Name = fileName.Substring(nameStartIndex, fileName.Length - nameStartIndex);
        model.Ver = "A";
    }
    else
    {
        verNext = fileName.Substring(numLastIndex + 1, 1);
        if (IsWord(numNext) && IsSpace(verNext))//1001001001A XXX承认书
        {
            model.Ver = numNext;
            int nameStartIndex = numLastIndex + 2;
            model.Name = fileName.Substring(nameStartIndex, fileName.Length - nameStartIndex);
        }
        else if (IsChinese(verNext = fileName.Substring(numLastIndex, 1))) //1001001001XXX承认书 (直接是编号+名称)
        {
            model.Name = fileName.Substring(numLastIndex, fileName.Length - numLastIndex);
            model.Ver = "A";
        }
        else
        {

        }
    }

    //有重复编号不添加
    foreach (Model item in list)
    {
        if (item.Num == model.Num)
        {
            return;
        }
    }

    list.Add(model);

}

还没完,接下来就是将获取的list写入Excel表格中

昨天刚学习了,C#操作Excel表格,今天就派上用场了,真爽

C#使用Microsoft.Office.Interop.Excel.操作Excel表格

用这方法需要导入Microsoft.Office.Interop.Excel.dll,在上面链接中可以下载

传入要导出的Excel表格路径

private void DataToExcel(string fileName)
{
    //应用程序
    Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
    //工作簿
    Workbook wbk = app.Workbooks.Open(fileName);
    //工作表
    Worksheet wsh = wbk.Sheets["Sheet1"];

    //写入数据
    for (int i = 0; i < list.Count; i++)
    {
        wsh.Cells[i + 1, 1] = list[i].Num;
        wsh.Cells[i + 1, 2] = list[i].Name;
        wsh.Cells[i + 1, 5] = list[i].Ver;
    }

    //保存
    wbk.Save();
    //退出
    app.Quit();
    //释放
    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
}