Daniloff
Помогающий
Offline
|
|
« : 14-09-2010 12:26 » |
|
Имеется файл заранее известного формата. В С++ для его загрузки в память я описываю структуру, выделяю память, подгружаю данные из файла в выделенную область и обращаюсь к ней через указатель структуры. Элементарно. А вот как быть с C#?..
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #1 : 14-09-2010 12:38 » |
|
Можно воспользоваться классом BitConverter, он имеет методы для преобразования последовательности байтов в основные скалярные типы-значения. Сами байты получать из потока, связанного с файлом.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #2 : 14-09-2010 15:54 » |
|
Я сам такой задачи не решал, но, по-моему, стоит смотреть в пространство имён System.Runtime.Serialization.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
KoctyaGold
Новенький
Offline
|
|
« Ответ #3 : 15-09-2010 11:45 » |
|
Если у вас предопределена структура файла, тогда можно использовать селиализацию. Но это медленный способ, чтобы заставить вашу программу быстрее работать, нужно применить маршалинг. Что я имею ввиду: Для того, чтобы прочитать какой-то файл, вы сначала предопределяете его структуру: пример: using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)] public struct MyStruct { public int field1; public uint field1; public float field1; public long field1; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public int[] array;// в єтом случае будет считываться массив из 2 элементов };
Только это должна быть структура, а не класс, или все что угодно, что не возвращает по умолчанию nullдалее, чтобы прочитать файл, используйте такой код: MyStruct entry = reader.ReadStruct<MyStruct>();
public static unsafe T ReadStruct<T>(this BinaryReader reader) where T : struct { byte[] rawData = reader.ReadBytes(Marshal.SizeOf(typeof(T))); GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned); T returnObject = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); handle.Free(); return returnObject; }
Этот код работает раз в 10 быстрее чем сериализация, но минус в том, что это небезопасный контекст, и чтоб скомпилировать его, нужно применить флаг компилятора /unsafe ЗЫ. Как читать сам файл или какими методами решать вам, я вам привел всего лишь пример, и но довольно таки ужатый. Проблема в том, что обычно файлы бывают сложных структур, и для каждого нужна своя логика, если вам не понятно или будут вопросы - спрашивайте. Пример функции чтения подобного файла табличной структуры с заголовочными параметрами. http://paste2.org/p/988835
|
|
|
Записан
|
|
|
|
Dimka
Деятель
Команда клуба
Offline
Пол:
|
|
« Ответ #4 : 15-09-2010 14:24 » |
|
Если данные записаны в специфическом формате, когда обычная сериализация не работает, можно написать собственную - через Reflections находить поля структуры, определять их типы и согласно ним вызывать либо методы чтения простых типов у BinaryReader с нужными преобразованиями, либо рекурсивно вызывать эту же функцию для вложенных структур.
Но Reflections работает небыстро.
|
|
|
Записан
|
Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел)
|
|
|
KoctyaGold
Новенький
Offline
|
|
« Ответ #5 : 15-09-2010 19:42 » |
|
Если данные записаны в специфическом формате, когда обычная сериализация не работает, можно написать собственную В данном случае, надо описание структуры файла, чтоб знать что посоветовать автору. Ибо все зависит от структуры файла, и вариант его чтения могут быть разными.
|
|
|
Записан
|
|
|
|
Daniloff
Помогающий
Offline
|
|
« Ответ #6 : 16-09-2010 05:08 » |
|
файл состоит из байтовых полей фиксированной длины. byte[100], byte[8],byte[8],byte[8],byte[12]...
|
|
|
Записан
|
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #7 : 16-09-2010 05:38 » |
|
Ну это простой случай. Интереснее когда структура содержит указатели, например struct Data { struct Data *Next; struct Data *Prev;
// something else } Unsafe код - это некрасиво. Какие тогда есть варианты, кроме прослойки на "плюсах"?
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #8 : 16-09-2010 05:53 » |
|
А в чем заключается смысл хранения указателей в файле?
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Dale
|
|
« Ответ #9 : 16-09-2010 05:57 » |
|
файл состоит из байтовых полей фиксированной длины. Массивы байтов просто считываются из потока методом Read.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #10 : 16-09-2010 06:06 » |
|
Dale, забыл дописать. Естесственно не в файле. В памяти. Когда получаешь данные извне. Причем бывает еще и так, что эти поля содержат на самом деле не указатель (хотя объявлены именно так), а смещение относительно начала буфера.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #11 : 16-09-2010 06:13 » |
|
Unsafe код - это некрасиво. Какие тогда есть варианты, кроме прослойки на "плюсах"? Я в таких случаях добавляю фабричный метод, который умеет считывать экземпляр из двоичного потока (и метод для записи в поток, если требуется).
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
Dale
|
|
« Ответ #12 : 16-09-2010 06:19 » |
|
Причем бывает еще и так, что эти поля содержат на самом деле не указатель (хотя объявлены именно так), а смещение относительно начала буфера. Мое IMHO: если поле объявлено как указатель и при этом хранит совершенно другие данные, таким объявлением лучше не пользоваться. Поскольку никто не мешает описать смещение именно как смещение. К тому же размер указателя зависит от разрядности платформы.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #13 : 16-09-2010 21:43 » |
|
К тому же размер указателя зависит от разрядности платформы.
Ну и что? если поле объявлено как указатель и при этом хранит совершенно другие данные, таким объявлением лучше не пользоваться. Поскольку никто не мешает описать смещение именно как смещение
Ну это ты просто не сталкивался с такими ситуациями, когда так приходится делать. Иногда требуется скопировать буфер из одного адресного пространства в другое. Допустим, ты объявишь структуру, в которой будут и поля-указатели и поля-смещения. Когда ты скопируешь буфер, указатели сразу станут невалидными. И для того, чтобы данные в этом новом буфере можно было прочитать, тебе надо будет перед копирование высчитать смещения, и занести их в соответствующие поля. Код который потом обрабатывает новый буфер естесствено не будет каждый раз, при доступе к данным, гемороиться со смещениями. Он пересчитает смещения в указатели (уже валидные). Таким образом, получается, что у тебя в структуре будут поля которые будут использованы один раз в жизни, и при этом (именно в это время) у тебя будут другие неиспользуемые поля (такое же их количество). Короче говнокод получится. По поводу считывания экземпляров из двоичного потока. Есть одно простое правило в C#: если используются указатели (даже внутри каких-то объектов), то это unsafe код. Пусть даже это будут какие-то дотнетовские объекты, а не твой код - все равно некрасиво. Само по себе, даже думать об указателях в C# это уже выходит за рамки его гармоничного мира. Для этого и делается плюсовая прослойка. Это что касается философии шарпа. Но если говорить о технической стороне, то выходит примерно тоже самое. Нельзя никак полагать что, то что в плюсах было указателем сойдет за ссылку на объект или что-то в этом духе.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #14 : 17-09-2010 05:25 » |
|
К тому же размер указателя зависит от разрядности платформы.
Ну и что? И то, что если поле структуры на разных платформах имеет разный размер, и при этом структура должна считываться из двоичного файла, это не способствует переносимости. Ну это ты просто не сталкивался с такими ситуациями, когда так приходится делать. Иногда требуется скопировать буфер из одного адресного пространства в другое. Допустим, ты объявишь структуру, в которой будут и поля-указатели и поля-смещения. ... Короче говнокод получится. Для подобных говнокодов специально заточен С, на котором всякие хаки делаются легко и непринужденно. C# несколько на другие задачи ориентирован, выбор его для кульбитов с адресными пространствами выглядит странновато. И вообще неплохо бы ответить на вопрос, который задал автор темы. А спросил он вполне конкретную вещь: как считать двоичные данные из файла в структуру. Когда спросит о копировании буфера из одного адресного пространства в другое, это будет уже другая тема.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
resource
Молодой специалист
Offline
Пол:
|
|
« Ответ #15 : 20-09-2010 20:47 » |
|
Да то что указатель хранится в структуре, это не означает, что его надо хранить в файле. Какие вообще в файле могут храниться указатели. Для этого и придумали смещения. Для подобных говнокодов специально заточен С, на котором всякие хаки делаются легко и непринужденно. C# несколько на другие задачи ориентирован, выбор его для кульбитов с адресными пространствами выглядит странновато Я, собственно, изначально сказал, что в таких ситуациях обычно делают "прослойку" на плюсах (если по-хорошему). И вообще неплохо бы ответить на вопрос, который задал автор темы А что, еще не ответили? Когда спросит о копировании буфера из одного адресного пространства в другое, это будет уже другая тема.
Извините пожалуйста. Больше не буду.
|
|
|
Записан
|
|
|
|
Dale
|
|
« Ответ #16 : 20-09-2010 21:44 » |
|
А что, еще не ответили?. Судить автору. Если сможет в этом разнообразии отыскать практически применимый ответ на первоначально заданный вопрос, то можно считать, что ответили. Извините пожалуйста. Больше не буду. Ну что вы, оставьте... Было чрезвычайно познавательно.
|
|
|
Записан
|
Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
|
|
|
|