• 提取文件名(非查找文件)


    曾经有这么一个需要,就想自己实现一个。虽然我知道java内置文件操作的库而C++没有,但还是不想换语言(文人相轻,程序猿更相轻)。于是就上网找了一段C版本的代码,就是这个:

     1 #include <iostream>
     2 #include <vector>
     3 #include <string>
     4 #include <cstring>
     5 #include <io.h>
     6 using namespace std;
     7 /**
     8 *获取文件夹中所有文件名
     9     input
    10         path:   文件夹路径
    11         exd:    文件后缀,如为空则全选
    12     output
    13         files:  容器
    14 */
    15 void getFileName(string path, string exd, vector<string>& files)
    16 {
    17     /// 文件句柄
    18     long hFile = 0;
    19     /// 文件信息
    20     struct _finddata_t fileinfo;
    21     string pathName(path), exdName = "\*."+exd;
    22     if(hFile = _findfirst((pathName+exdName).c_str(), &fileinfo) != -1)
    23     {
    24         do
    25         {///如果有文件夹,迭代之
    26             if(fileinfo.attrib&_A_SUBDIR)
    27             {
    28                 if(strcmp(fileinfo.name,".") && strcmp(fileinfo.name,".."))
    29                     getFileName(pathName+"\"+fileinfo.name, exd, files);
    30             }
    31             else
    32             {
    33                 if(strcmp(fileinfo.name,".") && strcmp(fileinfo.name,".."))
    34                     files.push_back(fileinfo.name);
    35             }
    36         }while(_findnext(hFile, &fileinfo)==0);
    37         /**这段代码跑出来实际上只能找到一个文件就结束了,找原因还很麻烦
    38         */
    39         _findclose(hFile);
    40     }
    41 }
    42 int main()
    43 {
    44     string path("E:");
    45     vector<string> files;
    46     getFileName(path,"",files);
    47     for(int i = 0; i < files.size(); i++)
    48         cout<<files[i]<<endl;
    49     return 0;
    50 }

    结果调了一上午还没调过,真是坑爹。

    后来发现用dos也能做,而且简单到让我想撞墙,就像这样

    @echo off
    dir /s/b *.txt > 文件名.txt
    exit

    就这么一行,dir就不用说了,/s表示递归遍历,/b表示一个文件一行,*.txt表示查找txt文件,然后写入到一个文件中。

    把它保存为bat,放入当前文件夹就可了。不过它输出的是绝对路径,还得自己再加工。

    问题是解决了,可是也太快了,我还没感觉呢。

    后来,我试着用NB的python解决,在实现的过程中,我感觉我就是在搞翻译。比如我知道要“获取当前文件夹”,然后python里是哪个函数有这个功能呢?找。我知道要“递归遍历”,但是python里是哪个函数有这个功能呢?找。大部分时间就是在看文档,学习语法,模块,并没有什么乐趣,也许是因为我对这个语言不熟吧。最后实现了递归与非递归两个版本,如下所示:

    1 import os
    2 import fnmatch
    3 f=open("图片.txt","w+")
    4 for file in os.listdir(os.getcwd()):
    5     if fnmatch.fnmatch(file, '*.jpg'):
    6         f.write(file+"
    ")
    7     #    f.write(os.path.realpath(file)+"
    ")
    8 f.close()
     1 import os
     2 import fnmatch
     3 f=open("图片.txt","w+")
     4 for tup in os.walk(os.getcwd()):
     5     lst = tup[2]
     6     dirpath = tup[0]
     7     for file in lst:
     8         if fnmatch.fnmatch(file, '*.jpg'):
     9             f.write(os.path.join(dirpath, file)+"
    ")
    10        #     f.write(file+"
    ")
    11 f.close()

    其中,getcwd()就是获取当前目录,listdir()是获取目录下所有子目录(非递归),walk()是递归获取,返回一个list of tuple,tuple包含三个元素,分别是当前目录,list of当前目录下的文件夹,list of当前目录下的文件。fnmatch()就是一个匹配的函数;realpath()返回绝对路径,join()连接路径。不得不说,脚本语言还是很方便的,源代码可以当exe直接运行。

    后来,我遇到了吊炸天的Boost,终于又可以用C++实现了。Boost的filesystem库实现了文件操作,而且它的可读性非常好,几乎不需要解读。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <string>
     4 #include <boost/filesystem/operations.hpp>
     5 using namespace std;
     6 using namespace boost;
     7 namespace fs = boost::filesystem;
     8 using rd_iter = fs::recursive_directory_iterator;
     9 using d_iter = fs::directory_iterator;
    10 int main()
    11 {
    12     string ext;
    13     cout<<"请输入文件格式(含.)"<<endl;
    14     cin>>ext;
    15     ofstream fout("output.txt");
    16     rd_iter pos("./"), End;
    17     for(; pos != End; ++pos)
    18     {
    19         if(!is_directory(*pos) &&
    20            pos->path().extension() == ext)
    21         {   //仅文件
    22         //    fout << pos->path().filename().string() << endl;
    23             //绝对路径
    24         //    fout << system_complete(pos->path()).string() << endl;
    25             //相对路径
    26             fout << pos->path().relative_path().string() << endl;
    27         }
    28     }
    29 }

    用"./"表示当前目录,多么简单直观。d_iter是非递归迭代器,rd_iter是递归迭代器,这里用迭代器来遍历路径。Boost把迭代器玩出魔性来了,好多用法第一次看的时候是跪着看的。更多的内容可以去看Chrono的书,这里就不说了。

  • 相关阅读:
    MongoDB之Limit及Skip方法
    MongoDB之$type操作符
    MongoDB之条件操作符
    MongoDB之文档的增删改查
    MongoDB之集合的创建与删除
    MongoDB之数据库的创建及删除
    MongoDB之术语解析
    很少用的U盘,今天居然无法打开(插入盘后能看到盘符但是无法打开的问题)
    IDEA安装后必须设置的选项
    IDEA2020离线更新迭代小版本
  • 原文地址:https://www.cnblogs.com/lzxskjo/p/4604400.html
Copyright © 2020-2023  润新知