от
Я пытаюсь прочитать двоичные данные с помощью C#. У меня есть вся информация о расположении данных в файлы, которые я хочу прочитать. Я в состоянии прочитать данные "чанк чанк", т. е. получать первые 40 байт данных, преобразования его в строку, сделать следующие 40 байт. Поскольку существует по крайней мере три слегка различные версии данных, я хотел бы прочитать данные непосредственно в структуру. Он просто чувствует себя так гораздо более правильно, чем читая его "построчно". Я попробовал следующий подход, но безрезультатно:
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;
}
Примеры кода изменяется от оригинала, чтобы сделать этот вопрос более короткие. Как мне читать двоичные данные из файла в структуру?

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.

8 Ответы

0 голосов
от
Я пытаюсь прочитать двоичные данные с помощью C#. У меня есть вся информация о расположении данных в файлы, которые я хочу прочитать. Я в состоянии прочитать данные "чанк чанк", т. е. получать первые 40 байт данных, преобразования его в строку, сделать следующие 40 байт. Поскольку существует по крайней мере три слегка различные версии данных, я хотел бы прочитать данные непосредственно в структуру. Он просто чувствует себя так гораздо более правильно, чем читая его "построчно". Я попробовал следующий подход, но безрезультатно:
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;
}
Примеры кода изменяется от оригинала, чтобы сделать этот вопрос более короткие. Как мне читать двоичные данные из файла в структуру?
0 голосов
от
Проблема струны в вашей структуре. Я обнаружил, что маршалинг типов, таких как байт/короткие/инт-это не проблема, но если требуется упаковать в сложный тип, например string, нужно свои структуры явно имитируют неуправляемого типа. Вы можете сделать это с помощью атрибута marshalas свойства. Для примера, следующее должно работать:
[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;
}
0 голосов
от
Вот что я использую.Это хорошо сработало для меня для чтения портативный исполняемый формат.Это общая функция, так
T
ваш тип
struct
.
public static T ByteToType
0 голосов
от
Как сказал Ронни, я использую BinaryReader и читать каждое поле по отдельности. Я не могу найти ссылку на статью с этой информацией, но было отмечено, что с помощью BinaryReader для чтения каждого отдельного поля может быть быстрее, чем Маршал.PtrToStruct, если структура содержит менее 30-40 или так поля. Я выложу ссылку на статью, когда я найти его. Ссылка в статье на: http://www.codeproject.com/Articles/10750/Fast-Binary-File-Reading-with-C При маршалинге массив структур, PtrToStruct одерживает верх, потому что вы можете думать графа поля как поля * длина массива.
0 голосов
от
Мне не повезло с помощью binaryformatter в, Я думаю, я должен иметь полную структуру, которая соответствует содержимое файла в точности. Я понял, что в конце концов я не был заинтересован в очень содержимое файла в любом случае, поэтому я пошел с решением значение части потока в bytebuffer и затем преобразовать его с помощью
Encoding.ASCII.GetString()
для строк и
BitConverter.ToInt32()
для целых чисел. Я должны быть в состоянии обработать больше файл позже, но на этой версии я отделался всего лишь парой строк кода.
0 голосов
от
Я не вижу никаких проблем с вашим кодом. просто из моей головы, что если вы попытаетесь сделать это вручную? это работает?
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();
затем с помощью буфера[] в вашем BinaryReader вместо чтения данных из файлового потока ли вы все равно получите исключение AccessViolation. Мне не повезло с помощью Класс binaryformatter, я думаю, я должен есть полная структура, которая соответствует содержимое файла в точности. В этом есть смысл, класс binaryformatter имеет свой собственный формат данных, полностью несовместимы с вашими.
0 голосов
от
Попробуйте это:
using (FileStream stream = new FileStream(fileName, FileMode.Open))
{
    BinaryFormatter formatter = new BinaryFormatter();
    StructType aStruct = (StructType)formatter.Deserialize(filestream);
}
0 голосов
от
Значение прямо структур зло - Многие программы C упала из-за разных байт порядков, различных реализаций компилятора полей, упаковки, размер слова....... Вы лучше serialising и deserialising байт за байтом. Использовать встроенный в вещи, если вы хотите или просто привыкнуть к BinaryReader.
...