Windows下使用_access和_stat判断文件和目录是否存在的区别

  判断一个文件和目录是否存在,可以使用_access或者_stat函数,但是要注意两点:

  1. _access能检测给定路径是否存在,但是无法区分这个路径是文件路径还是目录路径。比如指定路径d:\123,如果D盘下存在文件名为123的文件或者目录名为123的目录,_access返回信息都是存在的,但是无法区分这个路径是文件路径还是目录路径。_stat函数则能正确区分文件还是目录。
  2. 路径末尾是否能带有反斜杠“\”对于检测的结果也是不一样的:
    末尾是否能有"\"盘符目录文件
    本地网络本地网络UNC本地网络UNC
    _access无影响无影响无影响无影响无影响不能有"\"无影响无影响
    _stat必须有"\"必须有"\"不能有"\"不能有"\"不能有"\"不能有"\"不能有"\"不能有"\"

  以下是我写的测试程序来进行测试和结果,d:\123和t:\123是文件,d:\456和t:\456是目录,t盘是映射的\\172.16.254.101\d$\Lilong\tapefile\共享盘:

#include <cstdio>
#include  <stdio.h>
#include  <stdlib.h>
#include  <io.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <Windows.h>


void Test(char strPath[])
{  
	printf("%s\n", strPath);
	int nRet = _access(strPath, 0);
	int nErrNo = errno;

	printf("_access:nRet = %d, nErrNo = %d, LastErr = %d\n", nRet, nErrNo, GetLastError());

	struct _stat buf = {0};
	nRet = _stat(strPath, &buf);
	nErrNo = errno;
	printf("_stat:nRet = %d, nErrNo = %d, LastErr = %d, _S_IFDIR=%x, _S_IFREG=%x\n\n", 
		nRet, nErrNo, GetLastError(), buf.st_mode & _S_IFDIR, buf.st_mode & _S_IFREG);
}

int main(int argc, char* argv[])
{
	Test("");
	Test("d");
	Test("d:");
	Test("d:\\");
	Test("d:\\\\");
	Test("d:\\123");
	Test("d:\\123\\");
	Test("d:\\123\\\\");
	Test("d:\\456");
	Test("d:\\456\\");
	Test("d:\\456\\\\");
	Test("t");
	Test("t:");
	Test("t:\\");
	Test("t:\\123");
	Test("t:\\123\\");
	Test("t:\\456");
	Test("t:\\456\\");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile\\");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile\\123");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile\\123\\");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile\\456");
	Test("\\\\172.16.254.101\\d$\\Lilong\\tapefile\\456\\");

	return 0;
}


  以下是运行结果:
_access:nRet = -1, nErrNo = 2, LastErr = 3
_stat:nRet = -1, nErrNo = 2, LastErr = 3, _S_IFDIR=0, _S_IFREG=0

d
_access:nRet = -1, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

d:
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

d:\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 0, _S_IFDIR=4000, _S_IFREG=0

d:\\
_access:nRet = 0, nErrNo = 2, LastErr = 0
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=4000, _S_IFREG=0

d:\123
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=8000

d:\123\
_access:nRet = -1, nErrNo = 22, LastErr = 123
_stat:nRet = -1, nErrNo = 2, LastErr = 267, _S_IFDIR=0, _S_IFREG=0

d:\123\\
_access:nRet = -1, nErrNo = 22, LastErr = 123
_stat:nRet = -1, nErrNo = 2, LastErr = 267, _S_IFDIR=0, _S_IFREG=0

d:\456
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = 0, nErrNo = 2, LastErr = 267, _S_IFDIR=4000, _S_IFREG=0

d:\456\
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

d:\456\\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

t
_access:nRet = -1, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

t:
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

t:\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=4000, _S_IFREG=0

t:\123
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=8000

t:\123\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 267, _S_IFDIR=0, _S_IFREG=0

t:\456
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = 0, nErrNo = 2, LastErr = 267, _S_IFDIR=4000, _S_IFREG=0

t:\456\
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

\\172.16.254.101\d$\Lilong\tapefile
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=4000, _S_IFREG=0

\\172.16.254.101\d$\Lilong\tapefile\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

\\172.16.254.101\d$\Lilong\tapefile\123
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = 0, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=8000

\\172.16.254.101\d$\Lilong\tapefile\123\
_access:nRet = 0, nErrNo = 2, LastErr = 2
_stat:nRet = -1, nErrNo = 2, LastErr = 267, _S_IFDIR=0, _S_IFREG=0

\\172.16.254.101\d$\Lilong\tapefile\456
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = 0, nErrNo = 2, LastErr = 267, _S_IFDIR=4000, _S_IFREG=0

\\172.16.254.101\d$\Lilong\tapefile\456\
_access:nRet = 0, nErrNo = 2, LastErr = 267
_stat:nRet = -1, nErrNo = 2, LastErr = 2, _S_IFDIR=0, _S_IFREG=0

  为了更好的检测文件还是目录路径是否存在,我写了以下函数,能针对文件还是目录进行检测:

#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

// 返回值:
// 0:成功,指定的文件或目录路径存在
// ENOENT(2):指定的文件或目录路径不存在
// EINVAL(22):参数非法
// ENODEV(19):指定的路径存在,但是类型与指定的类型不一致
// 其他:其他错误
int IsPathExist(const CString strPathName, BOOL bCheckFilePath = TRUE)
{  
    CString strPathTmp(strPathName);

    strPathTmp.Replace(_T("/"), _T("\\"));
    strPathTmp.TrimRight(_T("\\"));
    if (1 == strPathTmp.GetLength()) // 驱动器盘符
    {
        strPathTmp += _T(":\\");
    }
    else if (2 == strPathTmp.GetLength() && strPathTmp.Right(1) == _T(":"))
    {
        strPathTmp += _T("\\");
    }

    struct _stat stPath = {0};
	int nRet = _tstat(strPathTmp, &stPath);

    do 
    {
        if (0 != nRet)
        {
            nRet = errno;
            break ;
        }

        BOOL IsFilePath = (_S_IFREG == (_S_IFREG & stPath.st_mode));
        BOOL IsDirPath = (_S_IFDIR == (_S_IFDIR & stPath.st_mode));

        if ((bCheckFilePath && !IsFilePath)
            || (!bCheckFilePath && !IsDirPath))
        {
            nRet = ENODEV;
        }

    } while (FALSE);

    return nRet;
}


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值