Как зайти в Даркнет?!
25th January, 01:11
5
0
Как в tkinter из поля ввода Entry получить значение в одну переменную и обновить строку кнопкой, затем получить ещё одно введённое значение и затем сложить их. Ниже пример кода
21st July, 19:00
893
0
Программа, которая создает фейковые сервера в поиске игровых серверов CS 1.6 Steam
21st March, 17:43
948
0
Очень долго работает Update запрос Oracle
27th January, 09:58
912
0
не могу запустить сервер на tomcat HTTP Status 404 – Not Found
21st January, 18:02
905
0
Где можно найти фрилансера для выполнения поступающих задач, на постоянной основе?
2nd December, 09:48
938
0
Разработка мобильной кроссплатформенной военной игры
16th July, 17:57
1724
0
период по дням
25th October, 10:44
3955
0
Пишу скрипты для BAS только на запросах
16th September, 02:42
3720
0
Некорректный скрипт для закрытия блока
14th April, 18:33
4613
0
прокидывать exception в блоках try-catch JAVA
11th March, 21:11
4381
0
Помогите пожалуйста решить задачи
24th November, 23:53
6086
0
Не понимаю почему не открывается детальное описание продукта
11th November, 11:51
4350
0
Нужно решить задачу по программированию на массивы
27th October, 18:01
4395
0
Метода Крамера С++
23rd October, 11:55
4309
0
помогите решить задачу на C++
22nd October, 17:31
4002
0
Помогите решить задачу на python с codeforces
22nd October, 11:11
4492
0
Python с нуля: полное руководство для начинающих
18th June, 13:58
2599
0
Чтение двоичного файла в структуру
Я пытаюсь читать двоичные данные с помощью C#. у меня есть вся информация о расположении данных в файлах, которые я хочу прочитать. Я могу читать данные "кусок за куском", т. е. получать первые 40 байт данных, преобразовывая их в строку, получать следующие 40 байт.
Поскольку существует по крайней мере три слегка отличающихся версии данных, я хотел бы прочитать данные непосредственно в структуру. Это просто кажется гораздо более правильным, чем при чтении его "line by line".
Я попробовал следующий подход, но безрезультатно:
StructType aStruct;
int count = Marshal.SizeOf(typeof(StructType));
byte[] readBuffer = new byte[count];
BinaryReader reader = new BinaryReader(stream);
readBuffer = reader.ReadBytes(count);
GCHandle handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned);
aStruct = (StructType) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(StructType));
handle.Free();
Поток-это открытый FileStream, из которого я начал читать. Я получаю AccessViolationExceptio n при использовании Marshal.PtrToStructure .
Поток содержит больше информации, чем я пытаюсь прочитать, так как меня не интересуют данные в конце файла.
Структура определяется следующим образом:
[StructLayout(LayoutKind.Explicit)]
struct StructType
{
[FieldOffset(0)]
public string FileDate;
[FieldOffset(8)]
public string FileTime;
[FieldOffset(16)]
public int Id1;
[FieldOffset(20)]
public string Id2;
}
Код примеров изменен с оригинала, чтобы сделать этот вопрос короче.
Как бы я мог читать двоичные данные из файла в структуру?
Проблема заключается в строке s в вашей структуре. Я обнаружил, что маршалинг таких типов, как byte/short/int, не является проблемой; но когда вам нужно маршалировать в сложный тип, такой как строка, вам нужно, чтобы ваша структура явно имитировала неуправляемый тип. Вы можете сделать это с помощью MarshalAs attrib.
Для вашего примера должно работать следующее:
[StructLayout(LayoutKind.Explicit)]
struct StructType
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string FileDate;
[FieldOffset(8)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
public string FileTime;
[FieldOffset(16)]
public int Id1;
[FieldOffset(20)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 66)] //Or however long Id2 is.
public string Id2;
}
Вот что я использую.
Это успешно сработало для меня при чтении портативного исполняемого формата.
Это универсальная функция, поэтому T - это ваш тип struct .
public static T ByteToType<T>(BinaryReader reader)
{
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T)));
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return theStructure;
}
Как сказал Ронни, я использую BinaryReader и читаю каждое поле индивидуально. Я не могу найти ссылку на статью с этой информацией, но было замечено, что использование BinaryReader для чтения каждого отдельного поля может быть быстрее, чем Marshal.PtrToStruct, если структура содержит меньше 30-40 или около того полей. Я отправлю ссылку на статью, когда найду ее.
Ссылка на статью находится по адресу: http://www.codeproject.com/Articles/10750/Fast-Binary-File-Reading-with-C
При маршалировании массива структур функция PtrToStruct быстрее получает преимущество, поскольку число полей можно представить как длину массива fields*.
Мне не повезло использовать BinaryFormatter, я думаю, что у меня должна быть полная структура, которая точно соответствует содержимому файла. Я понял, что в конце концов меня не очень интересует содержимое файла, поэтому я решил прочитать часть потока в bytebuffer, а затем преобразовать его с помощью
Encoding.ASCII.GetString()
для струн и
BitConverter.ToInt32()
для целых чисел.
Позже мне нужно будет разобрать больше файлов, но для этой версии мне сошло с рук всего несколько строк кода.
Я не вижу никаких проблем с вашим кодом.
просто из головы вылетело, а что если попробовать сделать это вручную? это работает?
BinaryReader reader = new BinaryReader(stream);
StructType o = new StructType();
o.FileDate = Encoding.ASCII.GetString(reader.ReadBytes(8));
o.FileTime = Encoding.ASCII.GetString(reader.ReadBytes(8));
...
...
...
также пробовать
StructType o = new StructType();
byte[] buffer = new byte[Marshal.SizeOf(typeof(StructType))];
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
Marshal.StructureToPtr(o, handle.AddrOfPinnedObject(), false);
handle.Free();
затем используйте buffer[] в вашем BinaryReader вместо чтения данных из FileStream, чтобы увидеть, получаете ли вы все еще исключение AccessViolation.
У меня не было удачи в использовании BinaryFormatter, я думаю, что должен это сделать иметь полную структуру, которая соответствует содержание файла точно такое же.
Это имеет смысл, BinaryFormatter имеет свой собственный формат данных, полностью несовместимый с вашим.
Чтение прямо в структуры является злом - многие программы C упали из-за различных порядков байтов, различных реализаций компилятора полей, упаковки, размера слова.......
Вы лучше всего сериализуете и десериализуете байт за байтом. Используйте встроенный материал, если хотите, или просто привыкайте к BinaryReader.