VC中文件(夹)目录与路径操作原理与代码实现

***********************************************声明*************************************************************************************

原创作品,出自 “晓风残月xj” 博客,欢迎转载,转载时请务必注明出处(http://blog.csdn.net/xiaofengcanyuexj)。

由于各种原因,可能存在诸多不足,欢迎斧正!

******************************************************************************************************************************************* 

最近在做安装包解压,涉及到很多关于路径的操作,当然很需要调用很多Windows API函数,本来是没有什么技术含量的,但由于Windows中关于目录、路径的操作较为重要,而且其中蕴含着一些重要的编程思想及技巧,所以在此加以总结,希望对以后的学习工作起到作用,同时更希望能帮助大家解决问题,共同创建一个知识分享型的网络社区。

现在提供以下几个操作方法,持续更新中…

    
  1、在指定路径下创建文件夹

2、获取程序的安装路径

3、对话框支持文件拖拽

4、获取当前进程已加载模块的文件的完整路径

5、文件(夹)的操作,如复制、删除、移动等

以下是详细介绍。

1、在指定路径下创建文件夹

void PathRemoveFileSpec(CString& strPath)
{
	int nPos = strPath.ReverseFind(_T('\\'));
	if (nPos == -1)
	{
		strPath.Empty();
	}
	else
	{
		strPath = strPath.Left(nPos);
	}
}

BOOL CreateDeepDirectory(LPCTSTR szPath)
{
	BOOL bRetCode = FALSE;
	CString strPath(szPath);
	if (GetFileAttributes(szPath) != INVALID_FILE_ATTRIBUTES)
		return TRUE;
	bRetCode = CreateDirectory(szPath, NULL);
	if (!bRetCode && GetLastError() != ERROR_ALREADY_EXISTS)
	{
		PathRemoveFileSpec(strPath);
		if (strPath.IsEmpty()) return FALSE;
		bRetCode = CreateDeepDirectory(strPath);
		if (!bRetCode) return FALSE;
		bRetCode = CreateDirectory(szPath, NULL);
		if (!bRetCode && GetLastError() != ERROR_ALREADY_EXISTS)
			return FALSE;
	}
	return TRUE;
}

2、获取程序的安装路径

     很多应用程序会在注册表中存储相应信息,此时可以从注册表中获取应用程序的安装路径

//InstallSoftwarePath.h

#ifndef _InstallSoftwarePath_H
#define _InstallSoftwarePath_H

class CInstallSoftwarePath
{
public:
	CInstallSoftwarePath(void);
	~CInstallSoftwarePath(void);
	 CString GetSoftwarePath(void);
private:
	CString m_cstrSoftwarePath;
};

#endif
//InstallSoftwarePath.cpp
#include "StdAfx.h"
#include "InstallSoftwarePath.h"

TCHAR g_szName[] = _T("XXX");//代表应用程序名

CInstallSoftwarePath::CInstallSoftwarePath(void)
{
	m_cstrSoftwarePath=_T("");
}

CInstallSoftwarePath::~CInstallSoftwarePath(void)
{
}

CString CInstallSoftwarePath::GetSoftwarePath(void)
{
	HKEY keyFirst = NULL, keySecond = NULL;
	TCHAR szSub[] = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
	TCHAR szName[200]   = {0};
	TCHAR szDisplay[200]  = {0};
	TCHAR szShow[200]   = {0};
	TCHAR szIcon[200] = {0};
	DWORD   dwIclen = 200;
	DWORD   dwIndex   = 0, dwNameSize = 200, dwShowLen = 200;
	DWORD   m_attr=REG_BINARY | REG_DWORD | REG_EXPAND_SZ | REG_MULTI_SZ | REG_NONE | REG_SZ; 

	if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSub, 0, KEY_ALL_ACCESS, &keyFirst))
	{
		while(ERROR_NO_MORE_ITEMS != RegEnumKeyEx(keyFirst, dwIndex, szName, &dwNameSize, 0, NULL, NULL, 0))
		{
			dwIndex++;
			if (0 != _tcscmp(szName, _T("")))
			{
				_tcscpy(szDisplay, szSub);
				_tcscat(szDisplay, _T("\\"));
				_tcscat(szDisplay, szName);
				if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDisplay, 0, KEY_ALL_ACCESS, &keySecond))
				{
					memset(szName, 0, sizeof(szName));
					memset(szShow, 0, sizeof(szShow));
					memset(szIcon, 0, sizeof(szIcon));
					dwIclen=200;
					dwNameSize = 200;
					dwShowLen = 200;
					RegQueryValueEx(keySecond, _T("DisplayName"), NULL, &m_attr, (LPBYTE)szName, &dwNameSize);
					RegQueryValueEx(keySecond, _T("DisplayIcon"), NULL, &m_attr, (LPBYTE)szIcon, &dwIclen);

					if(0 == _tcscmp(szName, g_szName))
					{
						if (keyFirst)
						{
							RegCloseKey(keyFirst);
						}
						if (keySecond)
						{
							RegCloseKey(keySecond);
						}
						m_cstrSoftwarePath=szIcon;
						m_cstrSoftwarePath.Remove('"');
						return  m_cstrSoftwarePath;
					}
				}
				memset(szName, 0, sizeof(szName));
				memset(szShow, 0, sizeof(szShow));
				memset(szDisplay, 0, sizeof(szDisplay));
				memset(szIcon, 0, sizeof(szIcon));
				dwIclen = 200;
				dwNameSize = 200;
				dwShowLen = 200;
			}
		}
	}
	if (keyFirst)
	{
		RegCloseKey(keyFirst);
	}
	if (keySecond)
	{
		RegCloseKey(keySecond);
	}
	m_cstrSoftwarePath = _T("");
	return m_cstrSoftwarePath;
}

GetSoftwarePath返回的就是应用程序g_szName的完整安装路径。

3、对话框支持文件拖拽

第一步、需要添加消息响应

WM_DROPFILES

1)、如果是MFC,操作如下:对话框上点击右键,选择Properties->Extended Styles,点选Accept files选项即可。

2)、如果不是MFC,如ATL、Win32、金山卫士开源代码等,操作如下:

LONG dwLong = GetWindowLong(GWL_EXSTYLE);
SetWindowLong(GWL_EXSTYLE, dwLong|WS_EX_ACCEPTFILES);

第二步、文件拖拽消息响应函数

void CMainDlg::OnDropFiles(HDROP hDropInfo)
{ 

	UINT count;
	TCHAR strFilePath[MAX_PATH + 1]   ;
	count = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
	if(count)
	{
		for(UINT i=0; i<count; i++)
                //支持多个文件的拖拽操作
		{
		    int pathLen = DragQueryFile(hDropInfo, i, strFilePath, sizeof(strFilePath));
                   //strFilePath存储的是当前文件的完整路径+文件名
                   //此处可以添加待处理的操作,完成应用程序的功能
		}
	}
	DragFinish(hDropInfo);
        //CDialog::OnDropFiles(hDropInfo);//如果是MFC,最好添加此操作
} 

4、获取当前进程已加载模块的文件的完整路径,该模块必须由当前进程加载

如下面的C:\Users\jimjxu\Desktop\我的程序\1.cpp源程序执行起来就是  "szPath = C:\Users\jimjxu\Desktop\我的程序\Debug\1.exe"

#include <windows.h>
#include <stdio.h>

BOOL GetExactFileName()
{
    TCHAR szPath[MAX_PATH];
    if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
    {
        printf("GetModuleFileName failed (%d)\n", GetLastError());
        return FALSE;
    }
	printf("szPath = %s\n", szPath);
	return TRUE;
}

int main(int argc, TCHAR* argv[])
{
	GetExactFileName();
	return 0;
}

5、文件(夹)的操作,如复制、删除、移动等

     关于文件的操作,较为简单,可以直接调用CopyFile,其原型为:

BOOL CopyFile(
LPCTSTR lpExistingFileName, // pointer to name of an existing file
LPCTSTR lpNewFileName,      // pointer to filename to copy to
BOOL bFailIfExists          // flag for operation if file exists
);
其中各参数的意义:
LPCTSTR lpExistingFileName, // 你要拷贝的源文件名
LPCTSTR lpNewFileName,      // 你要拷贝的目标文件名
BOOL bFailIfExists // 如果目标已经存在,true:不拷贝并返回False; false:覆盖目标. 

关于文件夹的操作,可能稍微复杂一点,文件夹表现为一组文件的集合,本质上和文件没什么区别。关于文件夹的操作,大致有2种方法:

第一种:递归复制单个文件注意处理,判断目录与文件,然后创建文件(夹)名称,递归复制文件;

第二种:调用Windows API处理,又分为MFC与Win32程序

如果是MFC程序,可以直接用CFileFind处理,有点第一种方法的味道,具体操作如下:

BOOL CopyDirectory(CString strSouDir, CString strDesDir)
{
	CFileFind finder;
	CString str, strWildcard, strFilePath, strDesFilePath;
	BOOL bRetCode ;
	if(strDesDir.Right(1) != _T("\\"))
		strDesDir += _T("\\");
	if(strSouDir.Right(1) != _T("\\"))
		strSouDir += _T("\\");
	strWildcard = strSouDir + _T("*.*");
	BOOL bContinue = finder.FindFile(strWildcard);
	while (bContinue)
	{
		bContinue = finder.FindNextFile();
		if(finder.IsDots())
		{
			continue;
		}
		str = finder.GetFileName();
		if(finder.IsDirectory())
		{
			CString temstrSouDir = strSouDir + str;
			CString temstrDesDir = strDesDir + str;
			CreateDirectory(temstrDesDir, NULL);
			ret = CopyDirectory(temstrSouDir, temstrDesDir);
		}
		else
		{
			strFilePath = finder.GetFilePath();
			strDesFilePath = strDesDir+str;
			bRetCode = CopyFile(strFilePath, strDesFilePath, FALSE);
			if(!bRetCode)
				break;
		}
	}
	finder.Close();
	return bRetCode;
}

如果是Win32程序,可以直接调用int SHFileOperation(LPSHFILEOPSTRUCT lpFileOp)处理,其中LPSHFILEOPSTRUCT结果如下:1.FO_COPY:复制

typedef struct _SHFILEOPSTRUCT {
 HWND hwnd;     //指向发送消息的窗口
 UINT wFunc;    //执行的操作
 LPCTSTR pFrom; //源文件名
 LPCTSTR pTo   ;//目标文件名
 FILEOP_FLAGS fFlags;        //操作与确认标识
 BOOL fAnyOperationsAborted; //操作是否终止
 LPVOID hNameMappings;       //文件映射
 LPCTSTR lpszProgressTitle;  //进度条标题
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

具体执行文件的操作只需设置相应的值即可,关于其他成员变量的设置及说明,请点击说明如下:

  1.FO_COPY:复制
 2.FO_DELETE:删除
 3.FO_MOVE:移动
 4.FO_RENAME:重命名

如下一段代码即可完成复制文件夹的操作:

BOOL KWork::CopyDir(LPCTSTR lpszSrcDir, LPCTSTR lpszDstDir)
{
	SHFILEOPSTRUCT sfo;
	ZeroMemory(&sfo, sizeof(sfo));
	sfo.wFunc = FO_COPY;
	sfo.pFrom = lpszSrcDir;
	sfo.pTo = lpszDstDir;
	sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
	int ret = SHFileOperation(&sfo);
	if ( ret == 0 )
		return TRUE;
	else
		return FALSE;
}

当然,对于不同的Windows程序,此处表现不同,是一大坑,具体说明点击说明

本文章持续更新中…

由于写博客时间有限,加之对VC不熟,难免有错误或不足的地方,欢迎斧正!

VC中文件(夹)目录与路径操作原理与代码实现

时间: 2024-10-14 10:24:06

VC中文件(夹)目录与路径操作原理与代码实现的相关文章

在使用Eclipse时出现的两个问题:“搞定 NiosII 工程文件夹目录路径改变”与“Connected system ID hash not found on target at expected base address”

问题一: “搞定 NiosII 工程文件夹目录路径改变”的过程中,按照<NiosII的奇幻漂流-v2.0.pdf>这本书附录一章<20.2 四步搞定 NiosII 工程文件夹目录路径改变>所说的方法进行问题解决的时候,总是会出现一些小问题,例如有一个问题“xxx.sopcinfo could not be found.”最后只能删掉工程,重建project,copy源码.虽然最后能够解决路径问题,但花费精力过多,无数次的删除原工程下的project,无数次的自己重建,虽然也能解决问

Mac 中显示资源库(Library)文件夹目录的几种方法

Mac 中显示资源库(Library)文件夹目录的几种方法 Mac中Library目录在10.6.7系统之后默认隐藏的,要想找到此文件夹有如下几种方法: 1. 用命令可以使其显示: 在终端中执行命令: chflags nohidden ~/Library 可显示资源库文件夹 如想隐藏,可以在终端中执行命令: chflags hidden ~/Library 隐藏 2. 在Finder菜单中的偏好设置中设置 在Finder菜单中的偏好设置中选择边栏,勾选上设备中的硬盘. 再打开Finder,Fin

C#中拷贝指定文件夹下的所有文件夹目录到指定文件夹中的方法

原文地址:http://www.biye5u.com/article/Csharp/fileprog/2011/4198.html 本文给出了一个在C#中拷贝指定文件夹下的所有文件夹目录到指定文件夹中的方法. public static void CopyFolder(string strFromPath,string strToPath){       //如果源文件夹不存在,则创建       if (!Directory.Exists(strFromPath))       {      

C#控制台基础 directory获取一个文件夹中所有文件及文件夹的绝对路径

1 探测的文件夹 2 代码 1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace directory创建一个文件夹 9 { 10 class Program 11 { 12 static void Main(string[] args)

linux系统下修改文件夹目录权限

linux系统下修改文件夹目录权限 文件夹权限问题 Linux.Fedora.Ubuntu修改文件.文件夹权限的方法差不多.很多人开始接触Linux时都很头痛Linux的文件权限问题.这里告诉大家如何修改Linux文件-文件夹权限.以主文件夹下的一个名为cc的文件夹为例. 下面一步一步介绍如何修改权限: 1.打开终端.输入su(没 Linux.Fedora.Ubuntu修改文件.文件夹权限的方法差不多.很多人开始接触Linux时都很头痛Linux的文件权限问题.这里告诉大家如何修改Linux文件

VC++中文件操作(一)---CFileFind,CFileDialog,CFile,CArchive,CStdioFile

各种关于文件的操作在程序设计中是十分常见,如果能对其各种操作都了如指掌,就可以根据实际情况找到最佳的解决方案,从而在较短的时间内编写出高效的代码,因而熟练的掌握文件操作是十分重要的.本文将对Visual C++中有关文件操作进行全面的介绍,并对在文件操作中经常遇到的一些疑难问题进行详细的分析. VC++中文件操作(一) ***************************************************************************××××××××××第一.V

NodeJS 将文件夹按照存放路径变成一个对应的JSON的方法

在编程之前,一定要有一个信条:代码是为了减少工作量而生的,重复枯燥的工作是不能容忍的. 需求 这是由上篇文章衍生出的需求,我已经将一个文件夹内所有的文件名转译为英文,但我在页面上还需要将这些图片引入加载.如果一个一个手写到程序里,未免有点劳心劳神.那么何不将这个文件夹按照存放路径变成一个相应的JSON在前端请求并渲染呢? 说干就干. 文件夹的路径如下所示: 一级路径:test二级路径:A,B,C...共十三个文件夹三级路径:每个二级路径下有3-8个文件夹不等四级路径:a.jpg,b.jpg,c.

高效系列:bat生成文件夹目录 & 折腾exe及icon配合

有时候我们需要新生成一套文件夹目录,就比如项目管理目录 大概的清单如下: ├─01.项目管理 │  ├─01.立项文档 │  ├─02.策划文档 │  ├─03.管理监控 │  ├─04.配置管理 │  ├─05.质量保证 │  ├─06.验收文档 │  ├─07.项目报告 │  ├─08.评审报告 │  ├─09.变更管理 │  ├─10.结项文档 │  ├─11.会议记录 │  └─12.其它文档 ├─02.需求文档 │  ├─01.用户需求说明书 │  └─02.需求规格说明书 ├─03.

删除沙盒中文件夹下所有文件

有时候需要在iOS系统里面,删除指定文件夹的内容,文件夹里面可能是文件,也可能包含有文件夹. 删除指定类型的文件.方法如下: NSString *extension = @"m4r"; NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,