Я пробовал два разных метода для чтения из этого файла cso. Какой шейдер Microsoft скомпилирован
HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
ScopedHandle hFile(safe_handle(CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr)));
LARGE_INTEGER fileSize = { 0 };
FILE_STANDARD_INFO fileInfo;
GetFileInformationByHandleEx(hFile.get(), FileStandardInfo, &fileInfo, sizeof(fileInfo));
fileSize = fileInfo.EndOfFile;
data.reset(new uint8_t[fileSize.LowPart]);
DWORD bytesRead = 0;
ReadFile(hFile.get(), data.get(), fileSize.LowPart, &bytesRead, nullptr);
*dataSize = bytesRead;
}
GetFileInformationByHandleEx вернул true
и ReadFile вернул true
HRESULT BasicReader::ReadData(_In_z_ wchar_t const* fileName, _Inout_ std::unique_ptr<uint8_t[]>& data, _Out_ size_t* dataSize) {
std::ifstream fstream;
fstream.open(fileName, std::ifstream::in | std::ifstream::binary);
if (fstream.fail())
return false;
char* val;
fstream.seekg(0, std::ios::end);
size_t size = size_t(fstream.tellg());
val = new char[size];
fstream.seekg(0, std::ios::beg);
fstream.read(val, size);
fstream.close();
auto f = reinterpret_cast<unsigned char*>(val);
data.reset(f);
*dataSize = size;
}
Оба эти метода делают данные = \ 0
Тем не мение; когда я указываю на другой файл в том же каталоге, он дает мне данные. Что здесь происходит?
Вот файл.
Я прочитал первые несколько байтов файла, и это так:
0 2 254 255 254 255 124 1 68 66 85 71 40 0 0 0 184 5 0 0 0 0 0 0 1 0 0 0 144 0 0
0 72 0 0 0 148 0 0 0 4 0 0 0 104 5 0 0 212 2 0 0 67 58 92 85 115 101 114 115 92
106 97 99 111 98 95 48 48 48 92 68 111 99 117 109 101 110 116 115 92 86 105 115
117 97 108 32 8...
И рабочий файл выглядит так:
68 68 83 32 124 0 0 0 7 16 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
32 0 0 0 0 64 0 0 0 0 0 0 0 32 0 0 0 0 0 255 0 0 255 0 0 255 0 0 0 0 0 0 0 0 16
0 0 0 0 0 0 0 0 0 0...
Ваш код работает должным образом: char* data
массив содержит данные файла. Что здесь происходит не так, что ваш char* data
ваши визуализаторы неправильно интерпретируют массив (все, что вы используете для визуализации: визуализатор отладчика, std::cout
, так далее). Все они пытаются напечатать строку с нулевым символом в конце (в стиле c), но она заканчивается мгновенно, так как первый символ равен 0. Необработанные массивы также можно визуализировать в отладчиках как указатели: адрес и только значение первого члена данных (потому что он не может знать, где массив заканчивается). В C # ситуация другая, так как массивы — это объекты, очень похожие на std::vector
с, так что их размер известен.
Оффтоп (извините за это):
Я хотел бы прокомментировать ваш второй, родной C ++ BasicReader::ReadData
Реализация метода, как это больно мои чувства C ++;) Вы пытаетесь написать код C в стиле C ++ 11. «Существует более одного способа снять шкуру с кошки», но есть несколько советов:
std::vector
, std::string
)std::unique_ptr<uint8_t[]> data
+ size_t dataSize
вместо std::vector<uint8_t>
?operator new()
, используйте контейнеры STL, std::make_shared
, std::make_unique
(если доступно)seekg()
+tellg()
подсчет размера файла может сообщить неправильный размер в случае больших файловРазве этот код не выглядит немного чище и безопаснее:
std::vector<uint8_t> ReadData(const std::string filename)
{
std::vector<uint8_t> data;
std::ifstream fs;
fs.open(filename, std::ifstream::in | std::ifstream::binary);
if (fs.good())
{
auto size = FileSize(filename);
// TODO: check here if size is more than size_t
data.resize(static_cast<size_t>(size));
fs.seekg(0, std::ios::beg);
fs.read(reinterpret_cast<char*>(&data[0]), size);
fs.close();
}
return data;
}
А использование еще чище:
std::vector<uint8_t> vertexShaderData = ReadData("VertexShader.cso");
if(vertexShaderData.empty()) { /* handle it*/ }
auto wannaKnowSize = vertexShaderData.size();
В качестве бонуса вы получили приятную визуализацию отладчика.
И безопасно FileSize()
реализация. Вы можете использовать любой boost :: filesystem, из std::tr2
если ваш STL реализовал это.
#include <filesystem>
namespace filesystem = std::tr2::sys;
/* or namespace filesystem = boost::filesystem */
uintmax_t FileSize(std::string filename)
{
filesystem::path p(filename);
if (filesystem::exists(p) && filesystem::is_regular_file(p))
return filesystem::file_size(p);
return 0;
}
Надеюсь, это поможет как-то.
Других решений пока нет …