2011-06-12 13 views
5

que tienen una estructura similar a C como esto:¿Cómo empiezo a leer en un desplazamiento en datos binarios?

SomeStruct << BinData::Record 
endian :little 

uint32 :offsetOfName 
uint32 :offsetOfLastname 
#... 
uint32 :lenVars 
struct :Person, :length => :lenVars 
    string :name 
    string :lname 
    #... 
end 

Tengo un montón de compensaciones y longitudes antes :Person. Todos los desplazamientos y longitudes describen los datos dentro de la estructura :Person.

¿Cómo puedo comenzar a leer datos en un desplazamiento especificado, para la longitud dada, o hasta el próximo desplazamiento?

Respuesta

3

Seek para compensar 1234 y luego leer 32 bytes en cadena s:

open 'some-binary-file', 'r' do |f| 
    f.seek 1234 
    s = f.read 32 
    # tho in your case, something like: 
    o = aBinData_object.read f 
    p s 
end 

Actualización: Parece que BinData entiende registros que codifican las longitudes de sus propios campos, pero dudo si hay alguna manera para hacer que te busque, a menos que estés dispuesto a codificar esencialmente campos ficticios del tamaño del espacio buscado y luego ignorar para siempre los datos que se saltan.

Sospecho que una buena solución implicará una búsqueda explícita y luego someBinDataObject.read(f) para obtener el registro.

+0

Esperaba una solución con BinData, pero gracias de todos modos. Saldré y jugaré un poco con el código, te contaré los resultados. – omninonsense

+0

He agregado una actualización menor. – DigitalRoss

+0

@DigitalRoss ¿Por qué lo estás leyendo en una cadena? abrir 'some-binary-file', 'r' do | f | f.seek 1234 o = aBinData_object.read f end ¿No sería eso suficiente? – thegreendroid

1

Docs para BinData: http://bindata.rubyforge.org/#nested_records

no están familiarizados con BinData así que tal vez estoy fuera de base aquí, pero los ejemplos parecen definir una clase para la estructura más externa:

class SomeStruct < BinData::Record 
... 

Entonces se habla de anidación estructuras anónimas dentro de esa clase:

struct :person do 
    ... 

Además, parece que le está dando a su estructura interna: persona una longitud. Supongo que la duración no se aplica aquí.

+0

Oh, la duración tiene que permanecer, pero no es tan relevante, realmente. Podría sacarlo, incluso. He leído la documentación varias veces, buscando lo que necesito, pero no pude encontrarlo, así que es por eso que recurrí a molestar a gente más inteligente aquí. : P – omninonsense

+0

Mi comprensión es que la longitud de una estructura (en c) es la suma de las longitudes de los tipos primitivos dentro de ella. Creé BinData :: Struct e intenté tomar la longitud: Obtuve este error: método indefinido 'length 'para {" a "=> 0}: BinData :: Struct – seph

2

BinData tiene dos opciones relacionadas con las compensaciones -: check_offset y: adjust_offset. Estos no están documentados en el manual, pero están documentados en bindata/offset.rb

Así es como funcionarían en su ejemplo.

class SomeStruct < BinData::Record 
    endian :little 

    uint32 :offsetOfName 
    uint32 :offsetOfLastname 
    #... 
    uint32 :lenVars 

    struct :person do 
    string :name, :adjust_offset => :offsetOfName, 
        :read_length => lambda { offsetOfLastName - offsetOfName } 
    string :lname, :adjust_offset => :offsetOfLastName, 
        :read_length => ... 
    #... 
    end 
end 
+0

¿Sabes si adjust_offset es absoluta o relativa? La documentación de API realmente falta en este sentido. – thegreendroid

+0

Miré la fuente y descubrí que es relativa. Sin embargo, necesito ajustar el desplazamiento en función del desplazamiento del archivo actual (io).Por ejemplo - : adjust_offset => (SOME_CONSTANT - currentOffset) ¿Cómo accedo al desplazamiento actual del archivo en el cierre (lambda)? – thegreendroid

Cuestiones relacionadas