检查真实文件后的假文件 "exist"?
Fake files "exist" after checking real files?
我在 Linux 上编写 C++ 有一段时间了,但最近搬到了 windows 10 计算机上。
我成功地使用 w64-mingw 设置了 CodeBlocks。
我一直在尝试将程序从 linux 移动到 windows,但我遇到了文件名方面的问题。例如,我有代码来检查文件或目录是否存在,以及创建目录。但是我得到了奇怪的结果,如果文件检查结果为真,那么所有后续文件检查结果都为真。我有示例代码,其中 test.txt 和 testdir 是最初不存在但由程序创建的文件和目录。 fail.txt 和 faildir 从不存在,但我的程序声称它们在创建 test.txt 和 testdir 之后存在。我已经看到几个关于检查 Windows 上是否存在文件的问题,但我从来没有 运行 遇到过这样的行为,我不确定发生了什么。调用 GetFileAttributes() 时 windows 是否无法重新初始化某些内容?还是我错过了一些非常基本的东西?
main.cpp
#include <iostream>
#include <fstream>
#include "../include/FileChecker.h"
int main(){
FileChecker fc = FileChecker();
std::cout << "Test Start" << std::endl;
#ifdef _WIN32
std::cout << "OS is windows" << std::endl;
#endif // _WIN32
std::cout << std::endl;
std::cout << "Nothing should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating test.txt" << std::endl;
std::ofstream test("test.txt");
test << "HELLO" << std::endl;
test.close();
std::cout << "Only test.txt should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating directory testdir" << std::endl;
if(fc.create_directory("testdir")){
std::cout << "Creation Success" << std::endl;
}else{
std::cout << "Creation Failed" << std::endl;
}
std::cout << "Only testdir should exist" << std::endl;
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
return 0;
}
FileChecker.h
#ifndef FILECHECKER_H
#define FILECHECKER_H
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <direct.h>
#endif // _WIN32
#include <string>
class FileChecker
{
public:
FileChecker();
virtual ~FileChecker();
bool file_exists(std::string filename);
bool directory_exists(std::string dirname);
bool create_file(std::string filename);
bool create_directory(std::string dirname);
protected:
private:
};
#endif // FILECHECKER_H
FileChecker.cpp
#include "../include/FileChecker.h"
FileChecker::FileChecker(){
//ctor
}
FileChecker::~FileChecker(){
//dtor
}
#ifdef _WIN32
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::directory_exists(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::create_directory(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
return(CreateDirectory(szPath, NULL));
}
#endif // _WIN32
输出
您的代码:
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
TEXT 只是转换,它不执行任何类型的转换。改成以下内容:
bool FileChecker::file_exists(std::string filename)
{
DWORD dwAttrib = GetFileAttributesA(filename.c_str());
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
您应该删除函数中的所有 static
关键字。
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str()); // <--- [*]
DWORD dwAttrib = GetFileAttributes(szPath);
当file_exists
函数第一次被调用时,szPath
变量被创建并初始化指向filename
的字符数组。当你第二次调用 file_exists
时,szPath
的值仍然相同,并指向无效数据(保留指向文件名对象数据的指针,该数据在第一次调用 file_exists
后被删除) .
您应该阅读函数中的静态变量。
我在 Linux 上编写 C++ 有一段时间了,但最近搬到了 windows 10 计算机上。
我成功地使用 w64-mingw 设置了 CodeBlocks。
我一直在尝试将程序从 linux 移动到 windows,但我遇到了文件名方面的问题。例如,我有代码来检查文件或目录是否存在,以及创建目录。但是我得到了奇怪的结果,如果文件检查结果为真,那么所有后续文件检查结果都为真。我有示例代码,其中 test.txt 和 testdir 是最初不存在但由程序创建的文件和目录。 fail.txt 和 faildir 从不存在,但我的程序声称它们在创建 test.txt 和 testdir 之后存在。我已经看到几个关于检查 Windows 上是否存在文件的问题,但我从来没有 运行 遇到过这样的行为,我不确定发生了什么。调用 GetFileAttributes() 时 windows 是否无法重新初始化某些内容?还是我错过了一些非常基本的东西?
main.cpp
#include <iostream>
#include <fstream>
#include "../include/FileChecker.h"
int main(){
FileChecker fc = FileChecker();
std::cout << "Test Start" << std::endl;
#ifdef _WIN32
std::cout << "OS is windows" << std::endl;
#endif // _WIN32
std::cout << std::endl;
std::cout << "Nothing should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating test.txt" << std::endl;
std::ofstream test("test.txt");
test << "HELLO" << std::endl;
test.close();
std::cout << "Only test.txt should exist" << std::endl;
if(fc.file_exists("test.txt")){
std::cout << "test.txt exists." << std::endl;
}else{
std::cout << "test.txt does not exist." << std::endl;
}
if(fc.file_exists("fail.txt")){
std::cout << "fail.txt exists." << std::endl;
}else{
std::cout << "fail.txt does not exist." << std::endl;
}
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
std::cout << std::endl;
std::cout << "Creating directory testdir" << std::endl;
if(fc.create_directory("testdir")){
std::cout << "Creation Success" << std::endl;
}else{
std::cout << "Creation Failed" << std::endl;
}
std::cout << "Only testdir should exist" << std::endl;
if(fc.directory_exists("testdir")){
std::cout << "Directory testdir exists." << std::endl;
}else{
std::cout << "Directory testdir does not exist." << std::endl;
}
if(fc.directory_exists("faildir")){
std::cout << "Directory faildir exists." << std::endl;
}else{
std::cout << "Directory faildir does not exist." << std::endl;
}
return 0;
}
FileChecker.h
#ifndef FILECHECKER_H
#define FILECHECKER_H
#ifdef _WIN32
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <direct.h>
#endif // _WIN32
#include <string>
class FileChecker
{
public:
FileChecker();
virtual ~FileChecker();
bool file_exists(std::string filename);
bool directory_exists(std::string dirname);
bool create_file(std::string filename);
bool create_directory(std::string dirname);
protected:
private:
};
#endif // FILECHECKER_H
FileChecker.cpp
#include "../include/FileChecker.h"
FileChecker::FileChecker(){
//ctor
}
FileChecker::~FileChecker(){
//dtor
}
#ifdef _WIN32
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::directory_exists(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
#endif // _WIN32
#ifdef _WIN32
bool FileChecker::create_directory(std::string dirname){
static LPCTSTR szPath = TEXT(dirname.c_str());
return(CreateDirectory(szPath, NULL));
}
#endif // _WIN32
输出
您的代码:
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str());
DWORD dwAttrib = GetFileAttributes(szPath);
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
TEXT 只是转换,它不执行任何类型的转换。改成以下内容:
bool FileChecker::file_exists(std::string filename)
{
DWORD dwAttrib = GetFileAttributesA(filename.c_str());
return ((dwAttrib != INVALID_FILE_ATTRIBUTES) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
您应该删除函数中的所有 static
关键字。
bool FileChecker::file_exists(std::string filename){
static LPCTSTR szPath = TEXT(filename.c_str()); // <--- [*]
DWORD dwAttrib = GetFileAttributes(szPath);
当file_exists
函数第一次被调用时,szPath
变量被创建并初始化指向filename
的字符数组。当你第二次调用 file_exists
时,szPath
的值仍然相同,并指向无效数据(保留指向文件名对象数据的指针,该数据在第一次调用 file_exists
后被删除) .
您应该阅读函数中的静态变量。