【问题标题】:c++ My method to get a files created date on windows os is crashing my console applicationc ++我在Windows操作系统上获取文件创建日期的方法使我的控制台应用程序崩溃
【发布时间】: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*

标签: c++


【解决方案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));
  • 我无法阅读您评论中的代码。请参阅日期/时间格式的更新答案。
  • 我看到你更新的答案。我感谢您提供的信息丰富的回答。它非常有用,并且避免了我在之前的评论中必须使用的解决方法。您无法阅读的注释中的代码(由于某种原因我无法编辑)要求您将 st 转换为 之类的类型,以便随后可以使用 std:: 将其转换为 wstring: to_wstring。此错误仅影响 Visual Studio 2010 的用户,但已在 Visual Studio 2012 中修复。
猜你喜欢
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 2018-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多