2

我已经尝试了几个小时,但我无法让我的DirectX12应用程序编写一个简单的文件......

关于我的设置:

  • Windows 10 更新。
  • DirectX12 默认的“旋转立方体”应用程序。DirectX 12 应用程序(通用 Windows)
  • 视觉工作室 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:\
  • 我在项目的每个文件夹中手动创建了文件...
  • 我已经尝试过调试和发布配置,以及 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();
}

谢谢埃比罗布!!

4

3 回答 3

4

看到这个答案:

std::fstream 不创建文件

您需要指定正确的选项wfstream::open()才能创建新文件。 ::inwithout::trunc将需要现有文件。

例子:

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

在这种情况下,似乎还有另一个问题。该应用程序是 Windows 10 应用商店的一部分,因此它只能访问少数几个位置的文件。

请看这个帖子:Can't create file using fstream in windows store app 8.1

有关如何在应用程序实际可以访问的本地或漫游用户配置文件目录中打开文件

于 2016-02-01T20:12:15.730 回答
1

这里的根本问题是发布者正在编写 UWP,而不是 Win32 桌面应用程序,这意味着该应用程序对文件系统的任意部分没有读写权限,特别是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 则没有。

于 2016-02-14T21:07:59.157 回答
0

我不知道到底出了什么问题,但我希望这段代码能帮助您诊断问题:

#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++ 上进行了测试。

于 2016-02-01T20:39:58.730 回答