Проверка файла с помощью GetFileAttributes(szPath) и GetLastError()

это продолжение "приведения типов LPCTSTR для использования с GetFileAttributes"

я расширил свой метод на GetLastError();.

Я привожу DWORD в беззнаковое целое и пытаюсь отобразить его с помощью MessageBox.

код работает, но я не могу визуализировать значение DWORD dw или Unsigned int test из метода GetLastError();, используя MessageBox и выясняя, как действовать дальше.

это проект win32, и я пытаюсь создать метод, чтобы увидеть, существует ли файл на жестком диске.

существует более 15 000 кодов ошибок, и невозможно жестко закодировать их все. http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx

BOOL FileExists(LPCTSTR szPath)
{
    //MessageBox(NULL,szPath,L"File Error",MB_OK);
    DWORD dwAttrib = GetFileAttributes(szPath);

    unsigned int test;
    DWORD dw = GetLastError();
    test =(unsigned int)dw;
    if(test == 0){
        MessageBox(NULL,(LPCWSTR)test, L"Target == 0",MB_OK);
    }
    else
    {
        MessageBox(NULL,(LPCWSTR)test, L"Target != 0",MB_OK);
    }

    switch(dw)
    {
    case ERROR_SUCCESS:
        MessageBox(NULL,L"ERROR_SUCCESS", L"File Error",MB_OK);
        break;
    case ERROR_PATH_NOT_FOUND:
        MessageBox(NULL,L"ERROR_PATH_NOT_FOUND", L"File Error",MB_OK);
        break;
    default:
        MessageBox(NULL,(LPCWSTR)dw, L"File Error",MB_OK);
        break;
    }

    switch(dwAttrib)
    {

        case FILE_ATTRIBUTE_DIRECTORY:
            MessageBox(NULL,L"FILE_ATTRIBUTE_DIRECTORY", L"File Error",MB_OK);
            break;
        case FILE_ATTRIBUTE_ARCHIVE:
            MessageBox(NULL,L"FILE_ATTRIBUTE_ARCHIVE", L"File Error",MB_OK);
            break;
        case FILE_READ_ONLY_VOLUME:
            MessageBox(NULL,L"FILE_READ_ONLY_VOLUME", L"File Error",MB_OK);
            break;
        case FILE_INVALID_FILE_ID:
            MessageBox(NULL,L"FILE_INVALID_FILE_ID", L"File Error",MB_OK);
            break;
        //case INVALID_FILE_ATTRIBUTES:
        //  MessageBox(NULL,L"INVALID_FILE_ATTRIBUTES",L"File Error",MB_OK);
        //  break;
        //case FILE_INVALID_FILE_ID:
        //  MessageBox(NULL,L"Failed to get image file,\\please check game folder",L"File Error",MB_OK);
        //  break;
        default:
            MessageBox(NULL,(LPCWSTR)dwAttrib,L"File Error",MB_OK);
            break;
    }

  return true; // testing phase
}

person NaturalDemon    schedule 29.05.2014    source источник
comment
FormatMessage. Кроме того, вы должны получить ваши основы прямо. Возьмите любое введение из Полное руководство и список книг C++.   -  person IInspectable    schedule 29.05.2014


Ответы (2)


Вы не можете ввести DWORD в строку. Вы должны отформатировать его.

Ваша проверка ошибок неверна.

В случае успеха GetFileAttributes() может (и часто возвращает) несколько атрибутов одновременно, но вы не обрабатываете эту возможность. И некоторые из значений, которые вы проверяете, даже не являются атрибутами значений.

Попробуйте это вместо этого:

BOOL FileExists(LPCTSTR szPath)
{
    DWORD dwAttrib = GetFileAttributes(szPath);
    if (dwAttrib == INVALID_FILE_ATTRIBUTES)
    {
        DWORD dw = GetLastError();
        switch (dw)
        {
            case ERROR_PATH_NOT_FOUND:
                MessageBoxW(NULL, L"ERROR_PATH_NOT_FOUND", L"File Error", MB_OK);
                break;

            case ERROR_FILE_NOT_FOUND:
                MessageBoxW(NULL, L"ERROR_FILE_NOT_FOUND", L"File Error", MB_OK);
                break;

            default:
            {
                std::wstringstream msg;
                msg << L"Error Code: " << dw;

                LPWSTR lpMsg = NULL;
                if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dw, 0, (LPWSTR)&lpMsg, 0, NULL))
                {
                    msg << std::endl << lpMsg;
                    LocalFree(lpMsg);
                }

                MessageBoxW(NULL, msg.str().c_str(), L"File Error", MB_OK);
                break;
            }
        }

        return false;
    }
    else
    {
        std::wstringstream attribs;

        if (dwAttrib & FILE_ATTRIBUTE_READONLY)
        {
            attribs << L"FILE_ATTRIBUTE_READONLY" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
        }

        if (dwAttrib & FILE_ATTRIBUTE_HIDDEN)
        {
            attribs << L"FILE_ATTRIBUTE_HIDDEN" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
        }

        if (dwAttrib & FILE_ATTRIBUTE_SYSTEM)
        {
            attribs << L"FILE_ATTRIBUTE_SYSTEM" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
        }

        if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)
        {
            attribs << L"FILE_ATTRIBUTE_DIRECTORY" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_DIRECTORY;
        }

        if (dwAttrib & FILE_ATTRIBUTE_ARCHIVE)
        {
            attribs << L"FILE_ATTRIBUTE_ARCHIVE" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
        }

        if (dwAttrib & FILE_ATTRIBUTE_DEVICE)
        {
            attribs << L"FILE_ATTRIBUTE_DEVICE" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_DEVICE;
        }

        if (dwAttrib & FILE_ATTRIBUTE_NORMAL)
        {
            attribs << L"FILE_ATTRIBUTE_NORMAL" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_NORMAL;
        }

        if (dwAttrib & FILE_ATTRIBUTE_TEMPORARY)
        {
            attribs << L"FILE_ATTRIBUTE_TEMPORARY" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_TEMPORARY;
        }

        if (dwAttrib & FILE_ATTRIBUTE_SPARSE_FILE)
        {
            attribs << L"FILE_ATTRIBUTE_SPARSE_FILE" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_SPARSE_FILE;
        }

        if (dwAttrib & FILE_ATTRIBUTE_REPARSE_POINT)
        {
            attribs << L"FILE_ATTRIBUTE_REPARSE_POINT" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_REPARSE_POINT;
        }

        if (dwAttrib & FILE_ATTRIBUTE_COMPRESSED)
        {
            attribs << L"FILE_ATTRIBUTE_COMPRESSED" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_COMPRESSED;
        }

        if (dwAttrib & FILE_ATTRIBUTE_OFFLINE)
        {
            attribs << L"FILE_ATTRIBUTE_OFFLINE" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_OFFLINE;
        }

        if (dwAttrib & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
        {
            attribs << L"FILE_ATTRIBUTE_NOT_CONTENT_INDEXED" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
        }

        if (dwAttrib & FILE_ATTRIBUTE_ENCRYPTED)
        {
            attribs << L"FILE_ATTRIBUTE_ENCRYPTED" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_ENCRYPTED;
        }

        if (dwAttrib & FILE_ATTRIBUTE_VIRTUAL)
        {
            attribs << L"FILE_ATTRIBUTE_VIRTUAL" << std::endl;
            dwAttrib &= ~FILE_ATTRIBUTE_VIRTUAL;
        }

        if (dwAttrib != 0)
            attribs << L"Other: " << std::hex << std::showbase << std::setw(8) << std::setfill(L'0') << dwAttribs << std::endl;

        MessageBoxW(NULL, attribs.str().c_str(), L"File Attributes", MB_OK);

        return true;
    }
person Remy Lebeau    schedule 29.05.2014
comment
Это не неопределенное поведение. Это определенное поведение. Временное выражение не уничтожается до тех пор, пока оно не выйдет из области видимости, и оно не выйдет из области видимости, пока не будет завершено все полное выражение. В этом случае, пока не будет вызвана и закрыта MessageBoxW(). - person Remy Lebeau; 29.05.2014
comment
это не окончательная версия метода, я просто выясняю, как визуализировать значения. но я принимаю во внимание ваш совет по нескольким атрибутам. Вы предлагаете какое-то время сделать какое-то время? сканировать несколько? - person NaturalDemon; 01.06.2014
comment
Спасибо, после добавления соответствующих заголовочных файлов все заработало и многое прояснилось, еще раз спасибо. - person NaturalDemon; 01.06.2014
comment
Вы пишете средство проверки существования файла. Единственный флаг, относящийся к этой логике, — FILE_ATTRIBUTE_DIRECTORY. Вместо этого остальная часть логики проверки полагается на GetLastError(). Если вы хотите отобразить атрибуты файла, вы должны написать для этой цели отдельную функцию. - person Remy Lebeau; 01.06.2014

Основная проблема, с которой вы столкнулись, заключается в том, что ваши броски неверны. Когда компилятор сообщает вам, что параметры, которые вы передаете, имеют неправильный тип, правильный подход состоит в том, чтобы найти способ передать что-то с правильным типом. Вместо этого вы приводите значение, которое просто говорит компилятору: «Я знаю лучше вас, пожалуйста, игнорируйте тип переменной и притворяйтесь, что это то, что я сказал».

Итак, вместо того, чтобы писать

(LPCWSTR)test

вам нужно преобразовать целое число test в широкую строку с нулевым завершением. Есть много способов сделать это. Например, вы можете использовать строковый поток:

std::wstringstream sstream;
sstream << test;
std::wstring str = test.str();

Затем вы можете передать str.c_str() API MessageBox.

В С++ 11 вы могли бы использовать std::to_wstring() следующим образом:

std::wstring str = std::to_wstring();

Вы неправильно интерпретируете значения, возвращаемые GetFileAttributes. Это комбинации битовых флагов. Другими словами, могут быть установлены несколько флагов атрибутов файла. Вам нужно использовать побитовый оператор и & для проверки наличия флагов.


Вы также неправильно проверяете ошибку. В документации говорится:

Если функция завершается ошибкой, возвращается значение INVALID_FILE_ATTRIBUTES. Чтобы получить расширенную информацию об ошибке, вызовите GetLastError.

Другими словами, вы должны вызывать GetLastError только тогда, когда GetFileAttributes возвращает значение INVALID_FILE_ATTRIBUTES. Это невероятно распространенная ошибка — думать, что на ошибки указывает GetLastError, возвращающее ненулевое значение. Вы должны прочитать документацию для каждой функции API, чтобы понять, как она сигнализирует об ошибках.


Наконец, если вы успешно получили действительный код ошибки Win32, используйте FormatMessage, чтобы получить текстовое описание ошибки.

person David Heffernan    schedule 29.05.2014
comment
Ваш ответ был очень информативным, я начал c ++ около 1,5 лет назад самостоятельно на диване. я пытаюсь понять сообщения от GetFileAttributes без жесткого кода всех возможностей. чтобы предотвратить заедание моего эксперимента с DirectX, потому что он не может найти файл bmp. Спасибо! - person NaturalDemon; 01.06.2014