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()新しいファイルを作成するには 、正しいオプションを指定する必要があります。::inなしで::truncは、既存のファイルが必要です。

例:

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

この場合、別の問題があるようです。このアプリケーションは Windows 10 アプリ ストアの一部であるため、いくつかの場所にあるファイルにしかアクセスできません。

このスレッドを参照してください: Windows ストア アプリ 8.1 で fstream を使用してファイルを作成できません

アプリが実際にアクセスできる ローカルまたはローミング ユーザー プロファイル ディレクトリ内のファイルを開く方法について。

于 2016-02-01T20:12:15.730 に答える
1

ここでの根本的な問題は、投稿者が Win32 デスクトップ アプリではなく UWP を作成していることです。つまり、アプリケーションには、ファイル システムの任意の部分、特にC:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt.

DirectX 12 を使用しているかどうかは、問題とは関係ありません。

UWP が直接アクセスできるファイル システムの部分は次のとおりです。

  • インストールされたパッケージ ディレクトリへの読み取り専用アクセス。Windows::ApplicationModel::Package::Current->InstalledLocation

  • 隔離された一時ファイル ディレクトリへの読み書きアクセス。Windows::Storage::ApplicationData::Current->TemporaryFolder

  • ローカルまたはローミングのいずれかで、ユーザーごと/アプリケーションごとに分離されたファイル ディレクトリへの読み取り/書き込みアクセス。Windows::Storage::ApplicationData::Current->LocalFolderまたはRoamingFolder;

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) にし、アプリケーション データには/を使用SHGetFolderPathし、一時ディレクトリにはへの読み取り/書き込みアクセス権があります。UWP では、残りのファイル システムは明示的に保護されますが、UAC ではそうではありませんでした。CSIDL_LOCAL_APPDATACSIDL_APPDATAGetTempPath

于 2016-02-14T21:07:59.157 に答える