簡體   English   中英

ofstream.is_open()在使用VS 2015的DirectX12應用程序中始終為false

[英]ofstream.is_open() always false in DirectX12 application using VS 2015

我已經嘗試了幾個小時,但我終生無法讓我的DirectX12應用程序編寫一個簡單的文件...

關於我的設置:

  • Windows 10已更新。
  • DirectX12默認為“旋轉多維數據集”應用程序。 DirectX 12 App(通用Windows)
  • Visual Studio 2015

我正在這樣做:

ofstream outFile;
// I have even tried with \\ slashes...
outFile.open("c://Users//pookie//Documents//WHERETHEFISMYFILE.txt");
if (outFile.is_open())
{
    outFile << "Writing this to a file.\n";
    outFile.close();
}

我嘗試過的東西(幾乎所有東西都在陽光和廚房水槽下):

  • 我也嘗試過使用fstreamwfstream以及!outfile.fail()
  • 我檢查了項目中的每個目錄,甚至嘗試使用Microsoft DirectX SDK。
  • 我已經嘗試過相對路徑: outFile.open("WHERETHEFISMYFILE.txt");
  • 我嘗試設置絕對路徑。
  • 我嘗試通過允許“所有人”並授予完全訪問權限來向文件夾添加權限-只是出於理智。
  • 我還嘗試獲取當前工作目錄,即C:\\Users\\pookie\\Documents\\Visual Studio 2015\\Projects\\demoDX12\\x64\\Debug\\demoDX12\\AppX並將其設置為c:\\
  • 我已經在項目的每個文件夾中手動創建了文件...
  • 我已經嘗試了Debug和Release配置,以及x86和x64及其所有可能的組合
  • 我已經在文件路徑中嘗試過\\\\//
  • 我嘗試用%20替換路徑中的空格
  • 我也嘗試過在管理員模式下運行Visual Studio。

這里發生問題: if (outFile.is_open()) 由於某種原因,它總是返回false。

我在這里做錯了什么?

更新:休息一下,我嘗試了一個空的控制台應用程序,其代碼如下:

#include <fstream>
#include <iostream>

using namespace std;

int main()
{
    try
    {
        wfstream  outFile;
        outFile.open("C:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt");
        if (outFile.is_open())
        {
            outFile << "Writing this to a file.\n";
            outFile.close();
        }
        else
        {
            cout << "sdsadsdsd";
        }
    }
    catch (const std::exception& ex)
    {
        cout << ex.what();
    }
    return 0;
}

結果是相同的: is_open() == false 伙計們,我真是茫然。

更新2:

根據要求,我正在更新此問題以顯示我正在處理的確切項目。 我正在使用默認的DirectX12應用程序-旋轉多維數據集。 遵循了本教程

在我的項目中,有一個名為void DX::DeviceResources::Present()方法,並且我正嘗試在該方法中寫入文件(盡管我也在該項目中的許多其他地方都嘗試過此方法。)

這里是:

// Present the contents of the swap chain to the screen.
void DX::DeviceResources::Present()
{
    // The first argument instructs DXGI to block until VSync, putting the application
    // to sleep until the next VSync. This ensures we don't waste any cycles rendering
    // frames that will never be displayed to the screen.
    HRESULT hr = m_swapChain->Present(1, 0);

    try
    {
        wfstream  outFile;
        std::string 
         //This has been done numerous ways, but ultimately, I believe that 
         //ios_base::out is required if the file does not yet exist.
        name("c:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt");
        outFile.open(name.c_str(), ios_base::out);
        if (outFile.is_open())
        {
            outFile << "Writing this to a file.\n";
            outFile.close();
        }
        else
        {
            cout << "sdsadsdsd";
        }
    }
    catch (const std::exception& ex)
    {
        cout << ex.what();
    }


    // If the device was removed either by a disconnection or a driver upgrade, we 
    // must recreate all device resources.
    if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
    {
        m_deviceRemoved = true;
    }
    else
    {
        DX::ThrowIfFailed(hr);

        MoveToNextFrame();
    }
}

更新3

因此,如果我使用帶有文件輸出的空白項目,效果很好

name("c:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt");
outFile.open(name.c_str(), ios_base::out);

注意ios_base::out

這可以。 但是,這在默認的DirectX12應用程序中仍然不起作用。

這絕對是DirectX相關的問題。 看到這個 我已經嘗試按照建議的解決方案進行操作,但是仍然無法正常工作。

我還可以確認一個全新的DirectX12項目也存在同樣的問題。 試試吧。

多虧了ebyrob,我才能完成這項工作。 事實證明,這些新的Windows應用程序只能寫入某些文件夾...更具體地說,這是:

auto platformPath = ApplicationData::Current->RoamingFolder->Path;

不幸的是,該路徑不是標准字符串...因此必須首先將其轉換:

auto platformPath = ApplicationData::Current->RoamingFolder->Path;
std::wstring platformPathW(platformPath->Begin());
std::string convertedPlatformPath(platformPathW.begin(), platformPathW.end());

然后只需添加文件名:

std::string path = convertedPlatformPath + "\\WHERETHFISMYFILE.txt";

最后:

try
{
    wofstream  outFile;
    char buff[256]; 
    outFile.open(path.c_str(), ios_base::out);
    if (outFile.is_open())
    {
        outFile << "Writing this to a file.\n";
        outFile.close();
    }
    else
    {
        cout << "Cannot open file " << name << ": " << strerror_s(buff,0) << endl;
    }
}
catch (const std::exception& ex)
{
    cout << ex.what();
}

謝謝ebyrob!

看到這個答案:

std :: fstream不創建文件

您需要為wfstream::open()指定正確的選項,以便創建一個新文件。 沒有::trunc ::in將需要一個現有文件。

例:

outFile.open("C:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt", ios_base::out);

在這種情況下,似乎還有另一個問題。 該應用程序是Windows 10應用程序商店的一部分,因此它只能訪問幾個位置的文件。

請查看此線程: 無法在Windows Store應用程序8.1中使用fstream創建文件

有關如何在應用程序確實可以訪問的本地或漫游用戶配置文件目錄中打開文件的信息。

根本問題在於發布者正在編寫UWP,而不是Win32桌面應用程序,這意味着該應用程序沒有對文件系統任意部分(特別是C:\\\\Users\\\\pookie\\\\Documents\\\\WHERETHEFISMYFILE.txt讀寫權限。 C:\\\\Users\\\\pookie\\\\Documents\\\\WHERETHEFISMYFILE.txt

是否使用DirectX 12與該問題無關。

UWP可以直接訪問的文件系統的唯一部分是:

  • 對已安裝的打包目錄的只讀訪問權限。 Windows::ApplicationModel::Package::Current->InstalledLocation

  • 對隔離的臨時文件目錄的讀寫訪問。 Windows::Storage::ApplicationData::Current->TemporaryFolder

  • 對本地或漫游的按用戶/按應用程序隔離的文件目錄的讀寫訪問。 Windows::Storage::ApplicationData::Current->LocalFolderRoamingFolder ;

要訪問UWP中的用戶文檔文件夾,需要使用Windows.Storage.Pickers Windows運行時文件選擇器,或通過具有適當聲明功能的StorageFile功能。 對於此類受保護的文件,您也不能直接使用C ++ iostream操作,因為它們甚至可能不是本地文件系統上的文件。 您可以使用Windows運行時API將文件復制到上述位置之一,然后在該副本上使用傳統的C / C ++函數。

這是一個使用C / C ++函數讀取位於受保護區域中的用戶文件(例如UWP中的用戶文檔)的示例:

#include <ppltasks.h>
using namespace concurrency;

using Windows::Storage;
using Windows::Storage::Pickers;

create_task(openPicker->PickSingleFileAsync()).then([](StorageFile^ file)
{
    if (file)
    {
        auto tempFolder = Windows::Storage::ApplicationData::Current->TemporaryFolder;
        create_task(file->CopyAsync(tempFolder, file->Name, NameCollisionOption::GenerateUniqueName)).then([](StorageFile^ tempFile)
        {
            if (tempFile)
            {
                ifstream inFile(tempFile->Path->Data())
                ...
            }
        });
    });
}

這是一個使用C / C ++函數編寫位於受保護區域中的用戶文件的示例,例如UWP中的用戶文檔:

#include <ppltasks.h>
using namespace concurrency;

using Windows::Storage;
using Windows::Storage::Pickers;

auto folder = Windows::Storage::ApplicationData::Current->TemporaryFolder;

WCHAR fname[ _MAX_PATH ];
wcscpy_s( fname, folder->Path->Data() );
wcscat_s( fname, L"\\MYFILE.txt" );

ofstream outFile;
outFile.open(fname, ios_base::out);

...

outFile.close();

create_task(savePicker->PickSaveFileAsync()).then([](StorageFile^ file)
{
    if ( file )
    {
        auto folder = Windows::Storage::ApplicationData::Current->TemporaryFolder;
        auto task = create_task( folder->GetFileAsync("MYFILE.txt") );
        task.then([file](StorageFile^ tempFile) ->IAsyncAction^
        {
            return tempFile->MoveAndReplaceAsync( file );
        });
    }
});

請參閱文件訪問和權限(Windows運行時應用程序)游戲的雙重用途編碼技術

請注意,遵循Windows Vista時代用戶帳戶控制准則的任何人都應該熟悉此模型,在該准則中,您的安裝目錄應該是只讀的(即,在C:\\Program Files ),並且應該將SHGetFolderPathCSIDL_LOCAL_APPDATA / CSIDL_APPDATA使用應用程序數據,並將GetTempPath用於您具有讀/寫訪問權限的臨時目錄。 使用UWP,文件系統的其余部分受到顯式保護,而UAC則沒有。

我不知道到底是哪里出了問題,但是我希望這段代碼可以幫助您診斷問題:

#include <iostream>
#include <fstream>
#include <string>
#include <string.h>

using namespace std;

int main()
{
    ofstream outFile;
    std::string name("c://Users//pookie//Documents//WHERETHEFISMYFILE.txt");
    outFile.open(name.c_str());
    if(outFile.is_open()) {
        outFile << "Writing this to a file.\n";
        outFile.close();
    } else {
        cout << "Cannot open file " << name << ": " << strerror(errno) << endl;
    }
}

此代碼已在此處在MSVC ++上進行了測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM