windows 文件,文件夹操作

一. C标准的文件读写

  • 操作方式:流式文件操作和I/O文件操作,这里只对流式文件操作进行说明,比较常用。
  • 特点:可移植性强(跨平台),如果是偏低层开发,与二进制文件打交道,会经常使用到该类函数。
  • 常用方法

   1. FILE流式文件的操作指针,下面简单说明一下这个结构体。

 1 typedef struct   _iobuf
 2 {
 3     char   *_ptr;           //文件输入的下一个位置 
 4     int    _cnt;            //当前缓冲区的相对位置 
 5     char   *_base;          //指基础位置(应该是文件的其始位置) 
 6     int    _flag;           //文件标志 
 7     int    _file;            //文件的有效性验证 
 8     int    _charbuf;        //检查缓冲区状况,如果无缓冲区则不读取 
 9     int    _bufsiz;            //文件的大小 
10     char   *_tmpfname;        //临时文件名 
11 }FILE;
View Code

   2. fopen_s:打开一个流并与文件关联,如果打开失败则返回相应的错误码。注:第三个参数mode设置为“a”时,如果文件不存在,则创建新文件,其他参数详解

   3. fclose关闭用fopen()打开的文件,如果打开成功返回0,失败则返回错误码。

   4. fseek一般用于二进制模式打开的文件中,功能是定位到流中指定的位置。第三个参数:SEEK_SET文件开头,SEEK_CUR文件当前读写位置,SEEK_END文件尾部。

   5. ftell:返回当前的文件位置。

   6. fwrite:往流中写入指定内容。文件操作是一个流程,将相关方法例子汇总到如下代码中。

 1     FILE* pFile = nullptr;
 2     const char* pcFilePath = ".//1.text";
 3 
 4     //文件写
 5     errno_t err = fopen_s(&pFile, pcFilePath, "ab");
 6     if ((0 == err) && (nullptr != pFile))
 7     {
 8         const char* pcData = "我们我们我们我们";
 9         UINT uiFileLen = strlen(pcData) + 1;
10 
11         UINT uiWriteLen = fwrite(pcData, sizeof (char), uiFileLen, pFile);
12         if (uiFileLen == uiWriteLen)
13         {
14             printf("file write successfully\n");
15         }
16         fclose(pFile);
17     }
View Code

   7. fread:从流中读取指定个数的字符。

 1     FILE* pFile = nullptr;
 2     const char* pcFilePath = ".//1.text";
 3 
 4     errno_t err1 = fopen_s(&pFile, pcFilePath, "r");
 5     if ((0 == err1) && (nullptr != pFile))
 6     {
 7         char acBuf[1024] = { 0 };
 8 
 9         fseek(pFile, 0, SEEK_END);
10         UINT uiFileLen = ftell(pFile);
11         fseek(pFile, 0, SEEK_SET);
12 
13         UINT uiReadLen = fread(acBuf, sizeof (char), uiFileLen, pFile);
14         if (uiReadLen == uiFileLen)
15         {
16             printf("file read: %s \n", acBuf);
17         }
18         fclose(pFile);
19     }
View Code

二. MFC封装的文件读写

  • 说明: c++也有流式文件操作,这里就不作说明了,只把自己常用的文件操作方式说明一下。
  • 特点:简洁方便,缺点也明显,只限于MFC环境。
  • 操作:

   1. CFile类:MFC类库将文件的一些相关操作封装到一个类里供我们使用,可参照类详细信息

   2. 文件相关:GetLength获取文件大小,对比C方法更简洁。GetFileName获取文件名,GetFilePath获取文件路径,Remove删除指定文件等。

   3. open:这里有nOpenFlgs的详细信息,其他与C的流式操作方法类似,下面就直接用例子说明。

 1     CFile objFile;
 2 
 3     //文件写
 4     BOOL bOpen = objFile.Open(_T(".//2.text"), CFile::modeCreate | CFile::modeWrite);
 5     if (TRUE == bOpen)
 6     {
 7         const PCHAR pcData = "我们会不会有明天";
 8         objFile.Write(pcData, (strlen(pcData) + 1) * sizeof (char));
 9         objFile.Close();
10     }
11 
12     //文件读
13     BOOL bOpen1 = objFile.Open(_T(".//2.text"), CFile::modeRead);
14     if (TRUE == bOpen1)
15     {
16         CHAR acBuf[1024] = { 0 };
17         UINT uiFileLen = (UINT)objFile.GetLength();
18 
19         UINT uiReadLen = objFile.Read(acBuf, uiFileLen);
20         if (uiReadLen == uiFileLen)
21         {
22             printf("MFC: file read: %s \n", acBuf);
23         }
24         objFile.Close();
25     }
View Code

三. MFC的文件对话框类CFileDialog

  •  说明:用来筛选文件或"另存为"文件,构造函数的参数说明如下:
1     CFileDialog ObjFileDlg(TRUE,    //指定要创建对话框的类型。若为"TRUE",则创建为"文件>打开"对话框;若为"FALSE",则创建为"文件>另存为"对话框。
2                            nullptr, //默认的文件扩展名。
3                            nullptr, //文件框显示的初始文件名。
4                            OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,//具体参见MSDN
5                            _T("图片文件(*.png; *.jpg; *.jpeg; *.bmp)|*.png; *.jpg; *.jpeg; *.bmp|所有文件(*.*)|*.*||"), //规则见文档说明 
6                            nullptr,//指向对话框的父窗口或所有者窗口  后面两个参数为缺省参数,可以不设置
7                            0,      //OPENFILENAME 结构的大小
8                            TRUE);  //指定文件对话框样式的参数
View Code

    1. dwFlags参数:请参见dwFlags参数说明

    2. lpszFilter:文件筛选器的过滤规则:eg .T("bmp文件(*.bmp)|*.bmp|JPEG文件(*.jpg)|*.jpg||") 

     

  • 打开文件夹:与CFileDialog类不同的是,打开"文件夹"对话框使用的win32 API
 1 void CFileDlgDlg::OnBnClickedBtnOpenfolder()
 2 {
 3     CString strDirPath;
 4     BROWSEINFO stDirInfo;
 5     ::ZeroMemory(&stDirInfo, sizeof(stDirInfo));
 6 
 7     stDirInfo.pidlRoot = 0;
 8     stDirInfo.lpszTitle = _T("选择文件存储路径:");
 9     stDirInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;
10     stDirInfo.lpfn = nullptr;
11 
12     LPITEMIDLIST lpidlBrowse = ::SHBrowseForFolder(&stDirInfo);
13     if (nullptr != lpidlBrowse)
14     {
15         if (::SHGetPathFromIDList(lpidlBrowse, strDirPath.GetBuffer(MAX_PATH)))
16         {
17             CEdit* pobjEditFolderPath = static_cast<CEdit*>(GetDlgItem(IDC_EDIT_FOLDERPATH));
18             if (nullptr != pobjEditFolderPath)
19             {
20                 pobjEditFolderPath->SetWindowTextW(strDirPath);
21             }
22         }
23         ::CoTaskMemFree(lpidlBrowse);
24     }
25 }
View Code
  • 测试代码:见最后链接,展示图如下:

四. windows API 下的文件及文件夹操作

  • 说明:CreateFile用来打开I/O设备。最常用的 I/O 设备如下:文件、文件流、目录、物理磁盘、卷、控制台缓冲区、磁带驱动器、通信资源、mailslot 和管道。比如,我们比较常用的对串口进行操作,就是使用此类函数,功能强大。

   1. CFile类的核心代码MFC封装的CFile类本质是对CreateFile,WriteFile,ReadFile,CloseHandle接口的封装;

   2. CreateFile除了可以打开文件外,还可以打开磁盘,驱动等,所以封装时作了兼容性处理

  • wprintf汉字时出现"??",跟大小端的存储格式有关,加上setlocale()可解决;当使用unicode输入汉字到文本后,使用记事本打开呈乱码,原因是系统自动识别为ANSI,可以在写入汉字之前,先写入“FEFF”
  • 打开文件后,直接进行读写操作时,一定要注意文件指针的位置,适当地使用SetFilePointer;
 1 #ifndef _FILEUTIL_H__
 2 #define _FILEUTIL_H__
 3 
 4 class ICallBackFile
 5 {
 6 public:
 7     virtual void CallBackEnumFiles(LPCTSTR lpFileName) = 0;
 8     virtual void CallBackOpenDlgFile(LPCTSTR lpFileName) = 0;
 9     virtual void CallBackOpenDlgDir(LPCTSTR lpDirName) = 0;
10 public:
11     ICallBackFile() = default;
12     virtual ~ICallBackFile() = default;
13 };
14 
15 class CFileUtil
16 {
17 public:
18     /*文件读写操作都是原子操作,使用单例来降低被重复并行操作的风险*/
19     static CFileUtil& GetInstance(); 
20 
21     /*创建文件*/
22     HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwCreationDisposition,
23         DWORD dwShareMode = 0, LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr,
24         DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, HANDLE hTemplateFile = nullptr);
25 
26     /*写文件*/
27     BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
28         LPOVERLAPPED lpOverlapped = nullptr);
29 
30     /*读文件*/
31     BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
32         LPOVERLAPPED lpOverlapped = nullptr);
33 
34     /*关闭文件句柄*/
35     BOOL CloseHandle( HANDLE hObject );
36 
37     /*获取文件大小*/
38     DWORD GetFileSize(HANDLE  hFile, LPDWORD lpFileSizeHigh = nullptr);
39 
40     /*设置文件指针位置*/
41     BOOL SetFilePointer(HANDLE hFile, LONGLONG llOffset, DWORD dwMoveMethod, PLARGE_INTEGER lpNewFilePointer = nullptr);
42 
43     /*删除文件*/
44     BOOL DeleteFile(LPCTSTR lpFileName);
45 
46     /*文件遍历:遍历指定目录下所有指定类型的文件(包含子目录的遍历)*/
47     void EnumFile(TCHAR* pcDirPath, TCHAR* pcFileExt);
48 
49     /*获取文件名:从完整的文件名路径中分离出文件名*/
50     PTSTR PathFindFileName(PTSTR ptFilePath);
51 
52     /*获取文件后缀名:从完整的文件名路径中分离出后缀名*/
53     BOOL  PathFindFileExt(PTSTR ptFilePath, PTSTR ptExtBuf, UINT uiBufSize);
54 
55     /*文件夹的创建*/
56     BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes = nullptr);
57 
58     /*文件夹的删除*/
59     BOOL RemoveDirectory(LPCTSTR lpPathName);
60 
61     /*选择文件:打开文件的对话框*/
62     void OpenDlgFile(HWND hWnd = nullptr, DWORD dwFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST, LPCTSTR lpFileType = _T("*.*"));
63 
64     /*选择文件夹:打开文件夹的对话框*/
65     void OpenDlgDir(LPCTSTR lpTitle = _T("选择文件夹"), UINT uiFlags = BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN | BIF_USENEWUI);
66 
67 public:
68     ICallBackFile* GetCallbackFile() const;
69     void SetCallbackFile(ICallBackFile* pCallbackFile);
70 
71 public:
72     CFileUtil() : m_pCallBackFile(nullptr) {};
73     CFileUtil(const CFileUtil&) = delete;//禁类赋值
74     CFileUtil& operator=(const CFileUtil&) = delete;//禁类拷贝
75 
76     ~CFileUtil() = default;
77 
78 private:
79     ICallBackFile* m_pCallBackFile;
80 };
81 
82 #endif /*_FILEUTIL_H__*/
View Code

 

posted @ 2021-05-13 19:35  夜不眠  阅读(193)  评论(0编辑  收藏  举报