// CodeLines.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <Commdlg.h>
#include <Shlobj.h>
#include <map>
#include <vector>
#include <iostream>
#include <io.h>
#include <string>
#include <set>
#include <fstream>
#pragma comment(lib,"Shell32.lib") void InitValidTypes(std::set<std::string> &validTypes)
{
validTypes.insert(".h");
validTypes.insert(".cpp");
validTypes.insert(".c");
validTypes.insert(".hpp");
validTypes.insert(".py");
validTypes.insert(".txt");
validTypes.insert(".cs");
validTypes.insert(".css");
validTypes.insert(".js");
validTypes.insert(".lua");
validTypes.insert(".html");
validTypes.insert(".htm");
validTypes.insert(".java");
validTypes.insert(".bat");
validTypes.insert("makefile");
} int32_t WToChar(LPWSTR szWstr, char szCstr[], const int32_t chrLen)
{
int iLength = WideCharToMultiByte(CP_ACP, , szWstr, -, NULL, , NULL, NULL);
return WideCharToMultiByte(CP_ACP, , szWstr, -, szCstr, iLength, NULL, NULL);
} void OpenDirectoryDialog(HWND hWnd, char directoryPath[], const int32_t directoryPathLen)
{
TCHAR szBuffer[MAX_PATH] = { };
BROWSEINFO bi = { };
bi.hwndOwner = hWnd;//拥有着窗口句柄,为NULL表示对话框是非模态的,实际应用中一般都要有这个句柄
bi.pszDisplayName = szBuffer;//接收文件夹的缓冲区
bi.lpszTitle = TEXT("选择一个文件夹");//标题
bi.ulFlags = BIF_NEWDIALOGSTYLE;
BOOL ret = FALSE;
do{
LPITEMIDLIST idl = SHBrowseForFolder(&bi);
ret = SHGetPathFromIDList(idl, szBuffer);
if (!ret)
{
MessageBox(NULL, TEXT("请选择一个文件夹"), NULL, MB_ICONERROR);
}
else
{
//MessageBox(NULL, szBuffer, TEXT("你选择的文件夹"), 0);
WToChar(szBuffer, directoryPath, directoryPathLen);
}
} while (!ret);
} void GetFilesFromDirectory(std::vector<std::string> &files, const char *directoryPath)
{
struct _finddata_t fileinfo;
long hFile = ;
char tmpPath[MAX_PATH] = { };
sprintf_s(tmpPath, "%s\\*", directoryPath);
if ((hFile = _findfirst(tmpPath, &fileinfo)) == -){ return; }
do
{
if ((fileinfo.attrib & _A_SUBDIR))
{
if (strcmp(fileinfo.name, ".") != && strcmp(fileinfo.name, "..") != )
{
sprintf_s(tmpPath, "%s\\%s", directoryPath, fileinfo.name);
GetFilesFromDirectory(files, tmpPath);
}
}
else
{
sprintf_s(tmpPath, "%s\\%s", directoryPath, fileinfo.name);
files.push_back(tmpPath);
}
} while (_findnext(hFile, &fileinfo) == );
_findclose(hFile);
} void StringToLower(std::string &str)
{
for (uint32_t i = ; i < str.length(); ++i)
{
if (str[i] >= 'A' && str[i] <= 'Z')
{
str[i] = str[i] + 'a' - 'A';
}
}
} std::string GetFileExtention(const std::string &fileName)
{
std::string localFileName = fileName;
StringToLower(localFileName);
int pos = localFileName.find_last_of('.');
if (pos >= )
{
return localFileName.substr(pos);
}
return localFileName;
} void DumpFiles(const std::vector<std::string> &files)
{
for (uint32_t i = ; i < files.size() && i < ; ++i)
{
std::cout << files[i] << std::endl;
std::cout << GetFileExtention(files[i]) << std::endl;
}
std::cout << files.size() << std::endl;
} bool IfFileTypeValid(const std::string &fileExtention)
{
static std::set<std::string> validTypes;
if (validTypes.empty()){
InitValidTypes(validTypes);
}
return validTypes.find(fileExtention) != validTypes.end();
} uint32_t CalculateCharShowTimesInBuf(char buf[], const uint32_t len, char aim)
{
uint32_t i = ,counter = ;
while (i < len && buf[i] != '\0')
{
if (buf[i] == aim){ ++counter; }
++i;
}
return counter;
} uint32_t GetFileLines(const std::string &fileName)
{
const uint32_t maxBufLen = ;
static char buf[maxBufLen + ];
std::ifstream inFile(fileName, std::ios::in);
if (!inFile){ return ; }
uint32_t counter = ;
while (!inFile.eof())
{
memset(buf, , maxBufLen);
inFile.read(buf, maxBufLen);
//std::cout << buf;
counter += CalculateCharShowTimesInBuf(buf, maxBufLen, '\n');
}
return counter;
} void StatisticCodeLines(std::map<std::string, uint32_t> &codeLines, const std::string &directoryPath)
{
static std::vector<std::string> files;
files.clear();
GetFilesFromDirectory(files, directoryPath.c_str());
// DumpFiles(files);
for (const std::string &fileName : files)
{
std::string fileExtention = GetFileExtention(fileName);
if (!IfFileTypeValid(fileExtention)){ continue; }
codeLines[fileExtention] += GetFileLines(fileName);
}
} void PrintCodeLines(const std::map<std::string, uint32_t> &codeLines)
{
for (const std::pair<std::string, uint32_t> &p : codeLines)
{
printf("%-6s:%-8u\n", p.first.c_str(), p.second);
}
} int _tmain(int argc, _TCHAR* argv[])
{
char directoryPath[MAX_PATH] = { };
OpenDirectoryDialog(NULL, directoryPath, MAX_PATH);
std::cout << directoryPath << std::endl;
static std::map<std::string, uint32_t> codeLines;
codeLines.clear();
StatisticCodeLines(codeLines, directoryPath);
PrintCodeLines(codeLines);
getchar();
return ;
}

效果图:

C++ 一个统计文件夹下所有代码文件行数的小工具的更多相关文章

  1. 用Java实现将多级文件夹下的所有文件统一放到一个文件夹中

    每次下了电影(男生懂得呦),每部电影都放在一个单独的文件夹里,看的时候很是不方便啊,一直重复着进入文件夹.后退,再进.再退的操作,而手动把这些电影全部复制出来又太繁琐.因此为了解决这个问题,用IO写了 ...

  2. php 遍历一个文件夹下的所有文件和子文件

    php 遍历一个文件夹下的所有文件和子文件 <?php /** * 将读取到的目录以数组的形式展现出来 * @return array * opendir() 函数打开一个目录句柄,可由 clo ...

  3. Java基础面试操作题: File IO 文件过滤器FileFilter 练习 把一个文件夹下的.java文件复制到另一个文件夹下的.txt文件

    package com.swift; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File ...

  4. Java遍历一个文件夹下的全部文件

    Java工具中为我们提供了一个用于管理文件系统的类,这个类就是File类,File类与其它流类不同的是,流类关心的是文件的内容.而File类关心的是磁盘上文件的存储. 一,File类有多个构造器,经常 ...

  5. 读取指定文件夹下的全部文件,可通过正则进行过滤,返回文件路径数组 -- 基于node的一个函数

    var fs = require('fs'); // 模板文件夹路径 var templateDirectory = '../src'; //相对于当前文件的相对路径 //var templateDi ...

  6. Java——用程序编译一个文件夹下所有java文件到另一个文件夹下

    package com.java.test.a; import java.io.IOException; import java.util.ArrayList; import java.util.Ar ...

  7. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

  8. C/C++不同文件夹下包含头文件的方法及#include的使用

    转自:http://blog.sina.com.cn/s/blog_6e0693f70100so42.html 本文主要介绍了如何不同文件夹下使用预处理器指示符#include. 假设我们有如下一个工 ...

  9. 递归输出文件夹下的所有文件的名称(转自 MSDN)

    问题:如何输出给定文件夹目录下面的所有文件的名称? C#代码: using System; using System.IO; namespace MyTest { public class Progr ...

随机推荐

  1. HDU4067 Random Maze(最小费用最大流)

    题目大概说,给一张图,删除其中一些单向边,使起点s出度比入度多1,终点t入度比出度多1,其他点出度等于入度.其中删除边的费用是bi,保留边的费用是ai,问完成要求最小的费用是多少. 一开始我想到和混合 ...

  2. 每天一个linux命令--locate

    linux下,不知道自己安装的程序放在哪里了,可以使用locate命令进行查找. [hongye@dev107 ~]$ locate activemq.xml /home/hongye/hongyeC ...

  3. netty-学习笔记

    零.socket: http://haohaoxuexi.iteye.com/blog/1979837 一.NIO(1.0)非阻塞 NIO的特点: Buffer,缓冲区 Channel,管道 Sele ...

  4. Shell 编程基础之 Until 练习

    一.语法 until [ condition ] # 和while相反,当 condition 条件成立时,就终止回圈, 否则就持续进行回圈的程序段 do #执行内容 done 二.练习 输入用户输入 ...

  5. poj2612Mine Sweeper

    很简单的模拟题目,但在队内赛的时候一直WA了10发...我ca 题目没看懂,也不算,就是我以为摸到地雷他会标星(*) ,但其实还是(x),T_T #include <cstdio> #in ...

  6. XIII Open Cup named after E.V. Pankratiev. GP of Azov Sea

    A. Freestyle 如果逆序对为$0$,那么先手必败. 因为每次只能翻转长度为$4k+2$和$4k+3$的区间,所以每次操作之后逆序对的奇偶性一定会发生改变. 因此如果逆序对个数为偶数,则先手必 ...

  7. 隐式调用 Intent 大全, 很全

    http://ming-fanglin.iteye.com/blog/1061312 //调用浏览器 Uri uri = Uri.parse(""); Intent it  = n ...

  8. linux下定时重启tomcat

    工具/原料 linux tomcat 方法/步骤 编写tomcat_shutdown.sh: #!/bin/sh export JAVA_HOME=/home/oracle/jdk1..0_67/ e ...

  9. sencha做个简单的登录界面

    很多人都在群里问要一个好看的登录界面,我表示很无奈,哪有好看的,每个人的要求不一样,要好看的只有自己做. 下面是我自己整理的一个通用版的登录界面,稍做修改,很容易能变成你想要的界面, 不说废话,直接上 ...

  10. linux中,常用的账号管理命令

    创建新用户:adduser 用户名创建新用户并将其加入一个现有组中:adduser 用户名 -G 组名创建新用户并使其只属于该组:adduser 用户名 -g 组名创建用户密码:passwd 用户名创 ...