繁体   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