ofstream.is_open () всегда ложно в приложении DirectX12, использующем VS 2015

Я пытаюсь часами, и я не могу на всю жизнь получить мой DirectX12 приложение для записи простого файла …

Немного о моей настройке:

  • Windows 10 обновлена.
  • DirectX12 по умолчанию приложение «вращающийся куб». Приложение DirectX 12 (универсальный 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();
}

Что я пробовал (почти все под солнцем и раковиной):

  • Я также пытался использовать fstream, wfstream а также делать !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();
}

Спасибо ебыроб !!

1

Решение

Смотрите этот ответ:

std :: fstream не создает файл

Вам необходимо указать правильные параметры для wfstream::open() для того, чтобы создать новый файл. ::in без ::trunc потребуется существующий файл.

Пример:

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

В этом случае, кажется, есть другая проблема. Приложение является частью магазина приложений Windows 10, поэтому оно может обращаться к файлам только в нескольких местах.

Пожалуйста, посмотрите эту ветку: Не удается создать файл с помощью fstream в приложении Windows Store 8.1

О том, как открыть файл в локальных или перемещаемых каталогах профилей пользователей, которые на самом деле приложение делает получить доступ к.

4

Другие решения

Я не знаю, что именно идет не так, но я надеюсь, что этот код поможет вам диагностировать проблему:

#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 ++ Вот.

0

Основная проблема заключается в том, что автор пишет 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->LocalFolder или же RoamingFolder;

Чтобы получить доступ к папке пользовательских документов в UWP, необходимо использовать средства выбора файлов среды выполнения Windows в Windows.Storage.Pickers или через StorageFile функциональность с соответствующей заявленной возможностью. Для таких защищенных файлов вы также не можете напрямую использовать операции iostream C ++, поскольку они могут даже не быть файлом в локальной файловой системе. Вы можете использовать API среды выполнения Windows, чтобы скопировать файл в одно из указанных выше мест, а затем использовать традиционные функции 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 Runtime) а также Методы кодирования двойного назначения для игр

Обратите внимание, что эта модель должна быть знакома всем, кто следил за эпохой Windows Vista Контроль учетной записи пользователя руководящие принципы, где ваш каталог установки должен быть только для чтения (то есть под C:\Program Files), и вы должны были использовать SHGetFolderPath с CSIDL_LOCAL_APPDATA / CSIDL_APPDATA для данных приложения и использования GetTempPath для временных каталогов у вас есть доступ для чтения / записи. С UWP остальная часть файловой системы явно защищена, что для UAC не было.

0
По вопросам рекламы [email protected]