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_strcreated 的引用,这样你就有了

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(st.wMonth)) + L"/" + std::to_wstring(static_cast(st.wDay)) + L "/" + std::to_wstring(static_cast(st.wYear)) + L" " + std::to_wstring(static_cast(st.wHour)) + L":" + std:: to_wstring(static_cast(st.wMinute)) + L":" + std::to_wstring(static_cast(st.wSecond)) + L":" + std::to_wstring(static_cast(st.wMilliseconds)); 详细解释见下文:***.com/questions/10664699/… 我无法阅读您评论中的代码。请参阅日期/时间格式的更新答案。 我看到你更新的答案。我感谢您提供的信息丰富的回答。它非常有用,并且避免了我在之前的评论中必须使用的解决方法。您无法阅读的注释中的代码(由于某种原因我无法编辑)要求您将 st 转换为 之类的类型,以便随后可以使用 std:: 将其转换为 wstring: to_wstring。此错误仅影响 Visual Studio 2010 的用户,但已在 Visual Studio 2012 中修复。

以上是关于c ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 Linux C 代码和头文件编译 Windows DLL

使用.Bat删除在Windows 10上超过特定天数的文件[复制]

在Windows上创建文件夹后,文件上传不会移动

获取文件的绝对路径

Windows操作系统无法打开适用于Linux的文件名

在 VB.NET 中获取文件修改日期