Я пишу двоичный файл в C # с использованием класса BinaryWriter
using (var b = new System.IO.BinaryWriter(System.IO.File.Open("C:\\TextureAtlas0.txa",
System.IO.FileMode.Create)))
{
int count;
// Write the number of source rectangle entries
count = textureAtlas.Rectangles.Count;
b.Write(count);
for (int i = 0; i < count; ++i)
{
b.Write(textureAtlas.SpriteNames[i]);
b.Write(textureAtlas.Rectangles[i].X);
b.Write(textureAtlas.Rectangles[i].Y);
b.Write(textureAtlas.Rectangles[i].Width);
b.Write(textureAtlas.Rectangles[i].Height);
}
}
Затем я пытаюсь прочитать тот же файл в C ++, используя следующие шаги.
У меня есть структура, которая содержит данные в том же порядке, в котором они были написаны.
struct TextureAtlasEntry
{
std::string name;
int x;
int y;
int width;
int height;
};
Счет читается первым
int count;
fread(&count, sizeof(int), 1, LoadFile);
Затем я пытаюсь использовать значение счетчика, чтобы определить размер списка, в котором будут храниться данные. Я не могу использовать массив, так как значение для количества будет отличаться в зависимости от файла, который читается.
std::list<TextureAtlasEntry> entries;
fread(&entries, sizeof(TextureAtlasEntry), count, LoadFile);
fclose(LoadFile);
Код выше не работает. Я могу заставить счет быть прочитанным правильно, но команда memcpy вызывает нарушение доступа с fread и списком записей.
Как я могу правильно прочитать данные и должен ли я заменить фред на эквивалент C ++?
РЕДАКТИРОВАТЬ:
Теперь я могу прочитать весь двоичный файл в память, используя следующий код
ifstream::pos_type size;
char *memblock;
ifstream file ("TextureAtlas0.txa", ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char[size];
file.seekg (0, ios::beg);
file.read (memblock, size);
file.close();
printf("File content is in memory");
delete[] memblock;
}
else
{
printf("Unable to open file");
}
Теперь файл находится в памяти, как мне преобразовать данные char [] в данные структуры?
Согласно документация, BinaryWriter (String) пишет …
Строка с префиксом длины представляет длину строки путем добавления префикса к
строка один байт или слово, которое содержит длину этого
строка. Этот метод сначала записывает длину строки как UTF-7
закодировано целое число без знака, а затем записывает, что много символов в
поток с использованием текущей кодировки экземпляра BinaryWriter.
В вашем коде C ++ вы просто пытаетесь прочитать размер вашей структуры в нескольких байтах, который отличается от формата BinaryWriter.
Вы используете .NET для кода C ++? Если это так, просто используйте класс BinaryReader для чтения в файле.
Если нет, вам придется немного разбить прочитанное. Когда вы будете готовы прочитать имя, вам сначала нужно прочитать «UTF-7-кодированное целое число без знака», а затем прочитать еще много байтов, чтобы получить строку.
РЕДАКТИРОВАТЬ
Исходя из вашего комментария ниже, кажется, что вы не будете использовать C ++. NET, поэтому я думаю, что у вас есть два варианта. 1) Запишите данные в C # таким образом, чтобы вы могли прочитать их в C ++ (используя строки фиксированной длины). 2) Выясните, как BinaryWriter.Write () записывает данные, чтобы вы могли правильно их прочитать в C ++.
Псевдокод — я думаю, что-то вроде этого. Как я сказал в комментарии ниже, мой C ++ ржавый, но этот базовый алгоритм должен быть близок.
read from file int num - number of items
for (i=0;i<num;i++){
read int stringBytes - size of string
read string stringBytes bytes - the name
read int X4
create your struct and add to list/array/dictionary
}
Вместо проблемы строкового типа данных, описанной в другом ответе, здесь есть еще одна вещь. std::list
это doubly linked list
который содержит дополнительные указатели по своей природе, так что прямой fread/memcpy
Вероятно, не дает вам то, что вы сохранили в C # фрагмент.