Я пытаюсь часами, и я не могу на всю жизнь получить мой DirectX12 приложение для записи простого файла …
Немного о моей настройке:
Я делаю это:
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()
outFile.open("WHERETHEFISMYFILE.txt");
C:\Users\pookie\Documents\Visual Studio 2015\Projects\demoDX12\x64\Debug\demoDX12\AppX
и установив его c:\
\\
так же как //
в моем пути к файлуПроблема возникает здесь: 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();
}
Спасибо ебыроб !!
Смотрите этот ответ:
std :: fstream не создает файл
Вам необходимо указать правильные параметры для wfstream::open()
для того, чтобы создать новый файл. ::in
без ::trunc
потребуется существующий файл.
Пример:
outFile.open("C:\\Users\\pookie\\Documents\\WHERETHEFISMYFILE.txt", ios_base::out);
В этом случае, кажется, есть другая проблема. Приложение является частью магазина приложений Windows 10, поэтому оно может обращаться к файлам только в нескольких местах.
Пожалуйста, посмотрите эту ветку: Не удается создать файл с помощью fstream в приложении Windows Store 8.1
О том, как открыть файл в локальных или перемещаемых каталогах профилей пользователей, которые на самом деле приложение делает получить доступ к.
Я не знаю, что именно идет не так, но я надеюсь, что этот код поможет вам диагностировать проблему:
#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 ++ Вот.
Основная проблема заключается в том, что автор пишет 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 не было.