c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃
Posted
技术标签:
【中文标题】c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃【英文标题】:c++ My method to get a files created date on windows os is crashing my console application 【发布时间】:2016-10-21 20:47:46 【问题描述】:当我调用Created
方法时,它会使我的控制台应用程序崩溃。如果我将其注释掉,我的程序运行良好。我正在尝试获取共享网络驱动器(Windows 操作系统)上文件的创建日期,但我无法弄清楚错误是什么。我只想能够获得创建文件时的时间戳。如果我能修复这种方法来做到这一点,那就太好了。如果没有,任何将产生该文件创建时间的时间戳的替换方法都是可以接受的。非常感谢任何帮助或指导。
#pragma comment(lib, "th32.lib")
#define VC_EXTRALEAN
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <cstring>
#include <io.h>
//#include <dirent.h>
#include <stdio.h>
#include <shlwapi.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <strsafe.h>
using namespace std;
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message.c_str();
__int64 FileSize(const wchar_t* name) //, bool _true
WIN32_FILE_ATTRIBUTE_DATA fad;
std::wstring temp;
wchar_t* created;
wchar_t* error;
if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
error = L"Error";
return -1; // error condition, could call GetLastError to find out more
LARGE_INTEGER size;
size.HighPart = fad.nFileSizeHigh;
size.LowPart = fad.nFileSizeLow;
//return (wchar_t*) size.QuadPart;
return size.QuadPart;
const wchar_t* Created(const wchar_t* name) //, bool _true
WIN32_FILE_ATTRIBUTE_DATA fad;
//std::wstring temp;
std::wstring created;
SYSTEMTIME st;
if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
std::wstring error(L"Error");
return error.c_str(); // error condition, could call GetLastError to find out more
if (!FileTimeToSystemTime(&fad.ftCreationTime, &st))
std::wstring error(L"Error getting created Time");
return error.c_str(); // error condition, could call GetLastError to find out more
std::wstring month((wchar_t*)st.wMonth);
std::wstring day((wchar_t*)st.wDay);
std::wstring year((wchar_t*)st.wYear);
created = month + L"/" + day + L"/" + year;
//created = temp.c_str();
//created = st.wMonth + '/' + st.wDay + '/' + st.wYear;
return created.c_str();
int _tmain(int argc, _TCHAR* argv[])
std::wstring ap(L"//S001E002/Some Folder/");
std::wstring all(L"*");
std::wstring temp = ap + all;
const wchar_t* Hotels = temp.c_str();
const wchar_t* current = L".";
const wchar_t* parent = L"..";
wchar_t* pdf = L"/*.??f\0";
wchar_t* tif = L"/*.*f";
WIN32_FIND_DATA FindFileData;
std::vector<std::wstring> folders;
std::vector<std::wstring> vs;
HANDLE hFind;
std::wcout << "Hotels Folder directory: " << Hotels << "\n";
hFind = FindFirstFile(Hotels, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
do
if(FindFileData.dwFileAttributes & _A_SUBDIR)
temp = FindFileData.cFileName;
if ( wcscmp(temp.c_str(), current) == 0 || wcscmp(temp.c_str(), parent) == 0 )
else
folders.push_back(FindFileData.cFileName);
std::wcout << "Folder: " << FindFileData.cFileName << "\n";
//std::wcout << " equal? " << current << " : " << temp << " : " << parent << "\n";
while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
//std::wcout << "Folder: " << str << "\n";
for (int i = 0; i < folders.size(); i++)
//folders[i]
temp = ap + folders[i] + pdf;
const wchar_t* _files = temp.c_str();
std::wcout << "File Directory: " << _files << "\n";
hFind = FindFirstFile(_files, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
do
temp = FindFileData.cFileName;
if ( wcscmp(temp.c_str(), current) == 0 || wcscmp(temp.c_str(), parent) == 0 )
else
//std::wcout << "File: "<< FindFileData.cFileName ;
//std::wcout << " equal? " << current << " : " << temp << " : " << parent << "\n";
temp = ap + folders[i] + L"/" + FindFileData.cFileName;
vs.push_back(temp);
while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
else
temp = ap + folders[i] + L"/";
std::wcout << temp.c_str() << " | ";
std::cout << GetLastErrorAsString() << "\n";
/*for (auto item : vs)
std::wcout << item << "\n";*/
__int64 size;
const wchar_t* created;
std::cout << "\n" << "Start File Stats" << "\n";
for (int i = 0; i < vs.size(); i++)
size = FileSize(vs[i].c_str());
created = Created(vs[i].c_str());
std::wcout << vs[i] << " | File size: ";
std::wcout << size ;
std::wcout << " | Created: " << created << " | Error: " << GetLastErrorAsString;
std::wcout << "\n"; // , 1 << FileSize(vs[i].c_str(), 0)
std::cout << "\n" << "End File Stats" << "\n";
std::cout << GetLastErrorAsString() << "\n";
std::cout << "Folder count: " << folders.size() << "\n";
std::cout << "File count: " << vs.size() << "\n";
return 0;
【问题讨论】:
我们甚至没有 full 方法。以及执行跟踪(因为您添加了很多跟踪,它们可能很有用)。等等:调试器更有用。 1) 我会使用 wstringstream 来构建字符串。 2)您正在返回一个局部变量。 3) 你不能缩小到导致崩溃的那条线吗? @JohnnyMopp 以下行是发生错误的地方。 if (!FileTimeToSystemTime(&fad.ftCreationTime, &st)) std::wstring error(L"Error getting created Time");返回错误.c_str(); // 错误情况,可以调用 GetLastError 了解更多信息 @JohnnyMopp 将它放在 If 语句中现在可以避免崩溃,但我无法获得错误代码。我调用 GetLastErrorAsString() 但它没有返回错误。我真正想要的只是一种检索文件创建时间戳的方法。 您正在返回一个指向错误字符串的指针,该错误字符串在您从函数返回后已被销毁。不要那样做!我建议返回std::wstring
而不是 const wchar_t*
【参考方案1】:
std::wstring month((wchar_t*)st.wMonth);
std::wstring day((wchar_t*)st.wDay);
std::wstring year((wchar_t*)st.wYear);
created = month + L"/" + day + L"/" + year;
您不能使用强制转换将整数转换为字符串。这两种数据类型非常不同。您可以使用强制转换将int
转换为double
等,但不是这个。请改用std::to_wstring
。删除对错误字符串的c_str
和created
的引用,这样你就有了
std::wstring created =
std::to_wstring(st.wMonth) + L"/" +
std::to_wstring(st.wDay) + L"/" +
std::to_wstring(st.wYear);
GetLastErrorAsString()
返回 ANSI 字符串,而程序的其余部分是 Unicode。您尝试使用以下内容来适应它:
std::wcout << GetLastErrorAsString << "\n"; <== error
但结果毫无意义。你应该把所有东西都变成 Unicode。此外,GetLastErrorAsString
不应返回 .c_str()
此外,除非函数失败或文档表明调用GetLastError()
有用,否则不要调用GetLastError()
。
if (FindFileData.dwFileAttributes & _A_SUBDIR)
这里使用的正确标志是FILE_ATTRIBUTE_DIRECTORY
。见File Attribute Constants
__int64 FileSize(const wchar_t* name)
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
return -1;
LARGE_INTEGER size;
size.HighPart = fad.nFileSizeHigh;
size.LowPart = fad.nFileSizeLow;
return size.QuadPart;
std::wstring Created(const wchar_t* name)
WIN32_FILE_ATTRIBUTE_DATA fad;
std::wstring created;
SYSTEMTIME st;
if (!GetFileAttributesEx(name, GetFileExInfoStandard, &fad))
std::wstring error(L"Error");
// error condition, could call GetLastError to find out more
return error;
if (!FileTimeToSystemTime(&fad.ftCreationTime, &st))
std::wstring error(L"Error getting created Time");
// error condition, could call GetLastError to find out more
return error;
created =
std::to_wstring(st.wMonth) + L"/" +
std::to_wstring(st.wDay) + L"/" +
std::to_wstring(st.wYear);
return created;
int main()
std::wstring ap(L"//S001E002/Some Folder/");
std::wstring all(L"*");
std::wstring temp = ap + all;
const wchar_t* Hotels = temp.c_str();
wchar_t* pdf = L"/*.??f\0";
WIN32_FIND_DATA FindFileData;
std::vector<std::wstring> folders;
std::vector<std::wstring> vs;
HANDLE hFind;
std::wcout << "Hotels Folder directory: " << Hotels << "\n";
hFind = FindFirstFile(Hotels, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
do
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
if (wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0)
continue;
folders.push_back(FindFileData.cFileName);
std::wcout << "Folder: " << FindFileData.cFileName << "\n";
while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
for (int i = 0; i < (int)folders.size(); i++)
temp = ap + folders[i] + pdf;
const wchar_t* _files = temp.c_str();
std::wcout << "File Directory: " << _files << "\n";
hFind = FindFirstFile(_files, &FindFileData);
if (hFind != INVALID_HANDLE_VALUE)
do
if (wcscmp(FindFileData.cFileName, L".") == 0 || wcscmp(FindFileData.cFileName, L"..") == 0)
continue;
temp = ap + folders[i] + L"/" + FindFileData.cFileName;
vs.push_back(temp);
while (FindNextFile(hFind, &FindFileData));
FindClose(hFind);
else
temp = ap + folders[i] + L"/";
std::wcout << temp.c_str() << "\n";
__int64 size;
std::cout << "\n" << "Start File Stats" << "\n";
for (int i = 0; i < (int)vs.size(); i++)
size = FileSize(vs[i].c_str());
std::wstring created = Created(vs[i].c_str());
std::wcout << vs[i] << " | File size: ";
std::wcout << size;
std::wcout << " | Created: " << created;
std::wcout << "\n";
std::cout << "\nEnd File Stats" << "\n";
std::cout << "Folder count: " << folders.size() << "\n";
std::cout << "File count: " << vs.size() << "\n";
return 0;
格式化日期/时间的更好方法是使用std::stringstream
//additional headers
#include <sstream>
#include <iomanip>
...
std::wostringstream oss;
oss << std::setfill(L'0');
oss
<< st.wMonth << L"/"
<< st.wDay << L"/"
<< st.wYear << L" "
<< std::setw(2) << st.wHour << L":"
<< std::setw(2) << st.wMinute << L":"
<< std::setw(2) << st.wSecond;
created = oss.str();
或者您可以使用 Windows 日期/时间格式:
wchar_t buf[100];
GetDateFormat(0, 0, &st, 0, buf, 100);
created = buf;
GetTimeFormat(0, 0, &st, 0, buf, 100);
created += std::wstring(L" ") + buf;
【讨论】:
非常感谢这解决了我的问题。阅读此解决方案的任何人都需要注意的一件事是,如果您像我一样使用 Visual Studio 2010。有一个需要以下内容的错误: created = std::to_wstring(static_cast以上是关于c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章
使用 Linux C 代码和头文件编译 Windows DLL