简体   繁体   English

ofstream.is_open()在使用VS 2015的DirectX12应用程序中始终为false

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

I've been trying for hours now, and I can't for the life of me get my DirectX12 application to write a simple file... 我已经尝试了几个小时,但我终生无法让我的DirectX12应用程序编写一个简单的文件...

A bit about my setup: 关于我的设置:

  • Windows 10 updated. Windows 10已更新。
  • DirectX12 default "spinning cube" application. DirectX12默认为“旋转多维数据集”应用程序。 DirectX 12 App (Universal Windows) DirectX 12 App(通用Windows)
  • Visual Studio 2015 Visual Studio 2015

I am doing this: 我正在这样做:

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();
}

What I have tried (almost everything under the sun and the kitchen sink): 我尝试过的东西(几乎所有东西都在阳光和厨房水槽下):

  • I've also tried using fstream , wfstream as well as doing !outfile.fail() 我也尝试过使用fstreamwfstream以及!outfile.fail()
  • I've checked every directory in my project, and even ventured out into the Microsoft DirectX SDK. 我检查了项目中的每个目录,甚至尝试使用Microsoft DirectX SDK。
  • I've tried relative paths: outFile.open("WHERETHEFISMYFILE.txt"); 我已经尝试过相对路径: outFile.open("WHERETHEFISMYFILE.txt");
  • I've tried setting an absolute path. 我尝试设置绝对路径。
  • I've tried adding permissions to the folder by allowing "everyone" and giving full access - just for sanity. 我尝试通过允许“所有人”并授予完全访问权限来向文件夹添加权限-只是出于理智。
  • I've also tried getting the current working directory, which is C:\\Users\\pookie\\Documents\\Visual Studio 2015\\Projects\\demoDX12\\x64\\Debug\\demoDX12\\AppX and setting it to c:\\ 我还尝试获取当前工作目录,即C:\\Users\\pookie\\Documents\\Visual Studio 2015\\Projects\\demoDX12\\x64\\Debug\\demoDX12\\AppX并将其设置为c:\\
  • I have created the file manually, in every folder of my project... 我已经在项目的每个文件夹中手动创建了文件...
  • I've tried in both Debug and Release configs, as well as x86 and x64 and all possible combinations thereof 我已经尝试了Debug和Release配置,以及x86和x64及其所有可能的组合
  • I've tried \\\\ as well as // in my file path 我已经在文件路径中尝试过\\\\//
  • I've tried replacing spaces in path with %20 我尝试用%20替换路径中的空格
  • I have also tried running Visual Studio in admin mode. 我也尝试过在管理员模式下运行Visual Studio。

The problem occurs here: if (outFile.is_open()) . 这里发生问题: if (outFile.is_open()) For some reason, it always returns false. 由于某种原因,它总是返回false。

What am I doing wrong here? 我在这里做错了什么?

UPDATE: To rest my mind, I tried an empty console application with the following code: 更新:休息一下,我尝试了一个空的控制台应用程序,其代码如下:

#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;
}

The result is the same: is_open() == false . 结果是相同的: is_open() == false I'm at a loss here guys. 伙计们,我真是茫然。

Update 2: 更新2:

As requested, I am updating this question to show the exact project I am working with. 根据要求,我正在更新此问题以显示我正在处理的确切项目。 I am working with the default DirectX12 application - the spinning cube. 我正在使用默认的DirectX12应用程序-旋转多维数据集。 I followed this tutorial 遵循了本教程

Within my project, there is a method called void DX::DeviceResources::Present() and it is within this method that I am trying to write to file (although I have tried this in numerous other places within this project, too. 在我的项目中,有一个名为void DX::DeviceResources::Present()方法,并且我正尝试在该方法中写入文件(尽管我也在该项目中的许多其他地方都尝试过此方法。)

Here it is: 这里是:

// 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();
    }
}

Update 3 更新3

So, a blank project with file output works fine, if I use 因此,如果我使用带有文件输出的空白项目,效果很好

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

Note the ios_base::out 注意ios_base::out

This is fine. 这可以。 However, this does still not work in the default DirectX12 application. 但是,这在默认的DirectX12应用程序中仍然不起作用。

This is definitely an DirectX related issue. 这绝对是DirectX相关的问题。 See this . 看到这个 I have tried doing as the solution in that post suggested, but I can still not get it to work. 我已经尝试按照建议的解决方案进行操作,但是仍然无法正常工作。

I can also confirm that a brand new DirectX12 project has the same issue. 我还可以确认一个全新的DirectX12项目也存在同样的问题。 Try it. 试试吧。

SOLUTION

Thanks to ebyrob, I have got this working. 多亏了ebyrob,我才能完成这项工作。 It turns out that these new Windows Apps can only write to certain folders... More specifically, this: 事实证明,这些新的Windows应用程序只能写入某些文件夹...更具体地说,这是:

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

Unfortunately, the path is not a standard string... so it must be converted first: 不幸的是,该路径不是标准字符串...因此必须首先将其转换:

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

Then just add the file name: 然后只需添加文件名:

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

and finally: 最后:

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();
}

Thank you ebyrob!! 谢谢ebyrob!

See this answer: 看到这个答案:

std::fstream doesn't create file std :: fstream不创建文件

You need to specify the correct options to wfstream::open() in order to create a new file. 您需要为wfstream::open()指定正确的选项,以便创建一个新文件。 ::in without ::trunc will require an existing file. 没有::trunc ::in将需要一个现有文件。

Example: 例:

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

In this case, it seems there is another issue. 在这种情况下,似乎还有另一个问题。 The application is part of Windows 10 app store, so it can only access files in a few locations. 该应用程序是Windows 10应用程序商店的一部分,因此它只能访问几个位置的文件。

Please see this thread: Can't create file using fstream in windows store app 8.1 请查看此线程: 无法在Windows Store应用程序8.1中使用fstream创建文件

For how to open a file in local or roaming user profile directories which the app actually does get access to. 有关如何在应用程序确实可以访问的本地或漫游用户配置文件目录中打开文件的信息。

The root problem here is that the poster is writing a UWP, not a Win32 desktop app, which means the application does not have read or write access to arbitrary parts of the file system, specifically C:\\\\Users\\\\pookie\\\\Documents\\\\WHERETHEFISMYFILE.txt . 根本问题在于发布者正在编写UWP,而不是Win32桌面应用程序,这意味着该应用程序没有对文件系统任意部分(特别是C:\\\\Users\\\\pookie\\\\Documents\\\\WHERETHEFISMYFILE.txt读写权限。 C:\\\\Users\\\\pookie\\\\Documents\\\\WHERETHEFISMYFILE.txt

The use of DirectX 12 or not has no bearing on the problem. 是否使用DirectX 12与该问题无关。

The only parts of the file system that a UWP can directly access are: UWP可以直接访问的文件系统的唯一部分是:

  • read-only access to the installed packaged directory. 对已安装的打包目录的只读访问权限。 Windows::ApplicationModel::Package::Current->InstalledLocation

  • read-write access to an isolated temporary file directory. 对隔离的临时文件目录的读写访问。 Windows::Storage::ApplicationData::Current->TemporaryFolder

  • read-write access to an isolated per-user/per-application file directory either local or roaming. 对本地或漫游的按用户/按应用程序隔离的文件目录的读写访问。 Windows::Storage::ApplicationData::Current->LocalFolder or RoamingFolder ; Windows::Storage::ApplicationData::Current->LocalFolderRoamingFolder ;

To get access to a user documents folder in a UWP requires using Windows Runtime file pickers in Windows.Storage.Pickers or via StorageFile functionality with an appropriate declared capability. 要访问UWP中的用户文档文件夹,需要使用Windows.Storage.Pickers Windows运行时文件选择器,或通过具有适当声明功能的StorageFile功能。 For such protected files, you also can't use C++ iostream operations directly as they might not even be a file on the local file system. 对于此类受保护的文件,您也不能直接使用C ++ iostream操作,因为它们甚至可能不是本地文件系统上的文件。 You could use Windows Runtime APIs to copy the file to one of the locations above, and then use traditional C/C++ functions on the copy there. 您可以使用Windows运行时API将文件复制到上述位置之一,然后在该副本上使用传统的C / C ++函数。

Here is an example of using C/C++ functions to read a user file located in a protected area like user documents in UWP: 这是一个使用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())
                ...
            }
        });
    });
}

Here is an example of using C/C++ functions to write a user file located in a protected area like user documents in UWP: 这是一个使用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 );
        });
    }
});

See File access and permissions (Windows Runtime apps) and Dual-use Coding Techniques for Games 请参阅文件访问和权限(Windows运行时应用程序)游戏的双重用途编码技术

Note that this model should be familiar to anyone who followed the Windows Vista era User Account Control guidelines where your install directory should be read-only (ie under C:\\Program Files ), and you were supposed to use SHGetFolderPath with CSIDL_LOCAL_APPDATA / CSIDL_APPDATA for application data, and use GetTempPath for temporary directories you have read/write access to. 请注意,遵循Windows Vista时代用户帐户控制准则的任何人都应该熟悉此模型,在该准则中,您的安装目录应该是只读的(即,在C:\\Program Files ),并且应该将SHGetFolderPathCSIDL_LOCAL_APPDATA / CSIDL_APPDATA使用应用程序数据,并将GetTempPath用于您具有读/写访问权限的临时目录。 With UWP, the rest of the file system is explicitly protected which for UAC it was not. 使用UWP,文件系统的其余部分受到显式保护,而UAC则没有。

I don't know what exactly is going wrong, but I hope this code will help you to diagnose the problem: 我不知道到底是哪里出了问题,但是我希望这段代码可以帮助您诊断问题:

#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;
    }
}

This code has been tested on MSVC++ here . 此代码已在此处在MSVC ++上进行了测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM