2010-10-04 14 views
11

En Perl, pack y unpack tienen dos plantillas para la conversión de bytes a/de hex:¿Cuándo utilizarías desempaquetar ('h *' ...) o paquete ('h *' ...)?

h       Una cadena hex (bajo nybble primero).
H       Una cadena hexadecimal (alta nybble primero).

Esto se clarifica mejor con un ejemplo:

use 5.010; # so I can use say 
my $buf = "\x12\x34\x56\x78"; 

say unpack('H*', $buf); # prints 12345678 
say unpack('h*', $buf); # prints 21436587 

Como se puede ver, H es lo que la gente en general quiere decir cuando piensan acerca de la conversión de bytes a/desde hexadecimal. Entonces, ¿cuál es el propósito de h? Larry debe haber pensado que alguien podría usarlo, o no se habría molestado en incluirlo.

¿Puede dar un ejemplo del mundo real en el que tendría en realidad desea utilizar en lugar de hH con pack o unpack? Estoy buscando un ejemplo específico; si conoce una máquina que organizó sus bytes de esa manera, ¿qué era y puede vincularse a cierta documentación sobre ella?

puedo pensar en ejemplos donde se puede usoh, tales como la serialización de algunos datos cuando no te importa lo que el formato es, siempre y cuando se puede leer de nuevo, pero H sería tan útil para eso. Estoy buscando a un ejemplo en el h es más útil que H.

Respuesta

9

Recall en las malas 'ole días de MS-DOS que ciertas funciones del sistema operativo fueron controlados mediante el establecimiento de media palabra alta y baja mordiscos en un registro y la realización de un xx Interupt. Por ejemplo, Int 21 accedió a muchas funciones de archivos. Usted establecería el nibble alto como el número de unidad, ¿quién tendrá más de 15 unidades? El nibble bajo como la función solicitada en esa unidad, etc.

Here es un código CPAN anterior que usa el paquete como usted describe para configurar los registros para realizar una llamada al sistema MS-DOS.

Blech !!! No echo de MS-DOS en absoluto ...

--Editar

Aquí está el código fuente específica: Descargar Perl 5,00402 para DOS HERE, descomprimir,

En el archivo de código de operación y Opcode.pm .pl se ve el uso de unpack("h*",$_[0]); aquí:

sub opset_to_hex ($) { 
    return "(invalid opset)" unless verify_opset($_[0]); 
    unpack("h*",$_[0]); 
} 

no seguía el código de todo el camino a través, pero mi sospecha es que esto es para recuperar información de una llamada al sistema de MS-DOS ...

enteros diferentes tiendas CPU y números de punto flotante en diferentes órdenes (llamados endianness) y anchos (3: en perlport para Perl 5,8-8, tienes estas pruebas para endianess del objetivo propuesto 2 bit y 64 bit siendo el más común hoy en día). Esto afecta a sus programas cuando intentan transferir números en formato binario de una arquitectura de CPU a otra, , generalmente "en vivo" a través de una conexión de red o almacenando los números en un almacenamiento secundario como un archivo de disco o cinta.

Las órdenes conflictivas de almacenamiento hacen un lío total de los números. Si un anfitrión ascendente hacia la izquierda (Intel, VAX) almacena 0x12345678 (305419896 en decimal), un host de big endian (Motorola, Sparc, PA) lee como 0x78563412 (2018915346 en decimal). Alpha y MIPS pueden ser: Digital/Compaq utilizado/los usa en modo little-endian; SGI/Cray usa en modo big-endian. Para evitar este problema en las conexiones de red (socket) use los formatos pack y unpackn y N, "network" orders. Se garantiza que sean portátiles.

A partir de Perl 5.8.5, también puede utilizar los modificadores > y < a la fuerza de orden de bytes o grande- ascendente hacia la izquierda. Esto es útil si quiere para almacenar enteros con signo o enteros de 64 bits, por ejemplo.

Puede explorar la orden de bits de su plataforma de desembalaje una estructura de datos envasado en formato nativo, tales como:

print unpack("h*", pack("s2", 1, 2)), "\n"; 
    # '10002000' on e.g. Intel x86 or Alpha 21064 in little-endian mode 
    # '00100020' on e.g. Motorola 68040 

Si es necesario distinguir entre las arquitecturas endian usted podría utilizar cualquiera de las variables establecidas como así:

$is_big_endian = unpack("h*", pack("s", 1)) =~ /01/; 
    $is_little_endian = unpack("h*", pack("s", 1)) =~ /^1/; 

anchuras divergentes pueden causar el truncamiento incluso entre las plataformas de igual endianness. La plataforma de ancho más corto pierde las partes superiores del número . No hay una buena solución para este problema, excepto para evitar transferir o almacenar números binarios en bruto.

Uno puede eludir estos dos problemas de dos maneras. De cualquier transferencia y almacenar números siempre en formato de texto, en lugar de prima binario, o bien considerar el uso de módulos como Data::Dumper (incluido en la distribución estándar como Perl de 5.005) y Storable (incluido como de Perl 5.8). Mantener todos los datos como texto simplifica significativamente las cosas.

el V-cadenas son portátiles sólo hasta v2147483647 (0x7FFFFFFF), eso es hasta qué punto EBCDIC, o más precisamente UTF-EBCDIC irá.

Parece que unpack("h*",...) se usa con más frecuencia que pack("h*",...). Hice notar que se utiliza en return qq'unpack("F", pack("h*", "$hex"))';Deparse.pmIO-Compress y utiliza pack("*h",...) en Perl 5.12

Si desea conocer más ejemplos, aquí es una Google Code Search list. Usted puede ver pack|unpack("h*"...) es bastante raro y sobre todo para determinar la compatibilidad de la plataforma ...

+0

Ese código usa' paquete', pero no usa ni 'h' ni' H' con él, solo 's' y' c'. – cjm

3

I imaginar este ser útil cuando la transferencia de datos hacia o lectura de datos desde una máquina con diferente endianess. Si algún proceso espera recibir datos de la forma en que normalmente lo representaría en la memoria, entonces será mejor que envíe sus datos de esa manera.

+0

No creo que endianess entre en esto, porque esto es nybbles _within_ byte. Los bytes aún se procesan en el mismo orden. – cjm

+4

mixto o endiaternidad media también existe. – rafl

+0

¿Puedes dar un ejemplo específico de esa máquina? – cjm

0

La distinción entre los dos sólo tiene que ver con si se está trabajando con datos en big endian o little-endian. A veces no tiene control sobre el origen o el destino de sus datos, por lo tanto, las banderas H y h están disponibles para darle la opción. V y N están ahí por la misma razón.

+1

No creo que endianess entre, porque esto es nybbles _within_ byte. Los bytes aún se procesan en el mismo orden. – cjm

+2

como se menciona por 'rafl', estos están ahí para el caso de una vez en un borde azul lunar donde tiene que lidiar con datos" divertidos ", piense en sistemas heredados y formatos de archivos binarios esotéricos pobremente documentados –