Puedo formatear un Erlang binario, de modo que cada byte está escrito en hexadecimal? I. e.,

> io:format(???, [<<255, 16>>]).
<<FF, 10>>

No veo una manera obvia de hacerlo en io:format documentación, pero tal vez simplemente estoy perdiendo uno? La conversión de binario a la lista y el formato de sus elementos por separado es demasiado ineficiente.

7 Comentarios

  1. 24

    No, no existe esa opción de formateo pero puedes hacer algo como:

    io:format("<<~s>>~n", [[io_lib:format("~2.16.0B",[X]) || <<X:8>> <= <<255,16>> ]]).

    Hay mucho más rápida solución si es necesario.

    -module(bin_to_hex).
    -compile([native, {hipe, [o3]}]).
    -export([bin_to_hex/1]).
    bin_to_hex(B) when is_binary(B) ->
    bin_to_hex(B, <<>>).
    -define(H(X), (hex(X)):16).
    bin_to_hex(<<>>, Acc) -> Acc;
    bin_to_hex(Bin, Acc) when byte_size(Bin) band 7 =:= 0 ->
    bin_to_hex_(Bin, Acc);
    bin_to_hex(<<X:8, Rest/binary>>, Acc) ->
    bin_to_hex(Rest, <<Acc/binary, ?H(X)>>).
    bin_to_hex_(<<>>, Acc) -> Acc;
    bin_to_hex_(<<A:8, B:8, C:8, D:8, E:8, F:8, G:8, H:8, Rest/binary>>, Acc) ->
    bin_to_hex_(
    Rest,
    <<Acc/binary,
    ?H(A), ?H(B), ?H(C), ?H(D), ?H(E), ?H(F), ?H(G), ?H(H)>>).
    -compile({inline, [hex/1]}).
    hex(X) ->
    element(
    X+1, {16#3030, 16#3031, 16#3032, 16#3033, 16#3034, 16#3035, 16#3036,
    16#3037, 16#3038, 16#3039, 16#3041, 16#3042, 16#3043, 16#3044,
    16#3045, 16#3046, 16#3130, 16#3131, 16#3132, 16#3133, 16#3134,
    16#3135, 16#3136, 16#3137, 16#3138, 16#3139, 16#3141, 16#3142,
    16#3143, 16#3144, 16#3145, 16#3146, 16#3230, 16#3231, 16#3232,
    16#3233, 16#3234, 16#3235, 16#3236, 16#3237, 16#3238, 16#3239,
    16#3241, 16#3242, 16#3243, 16#3244, 16#3245, 16#3246, 16#3330,
    16#3331, 16#3332, 16#3333, 16#3334, 16#3335, 16#3336, 16#3337,
    16#3338, 16#3339, 16#3341, 16#3342, 16#3343, 16#3344, 16#3345,
    16#3346, 16#3430, 16#3431, 16#3432, 16#3433, 16#3434, 16#3435,
    16#3436, 16#3437, 16#3438, 16#3439, 16#3441, 16#3442, 16#3443,
    16#3444, 16#3445, 16#3446, 16#3530, 16#3531, 16#3532, 16#3533,
    16#3534, 16#3535, 16#3536, 16#3537, 16#3538, 16#3539, 16#3541,
    16#3542, 16#3543, 16#3544, 16#3545, 16#3546, 16#3630, 16#3631,
    16#3632, 16#3633, 16#3634, 16#3635, 16#3636, 16#3637, 16#3638,
    16#3639, 16#3641, 16#3642, 16#3643, 16#3644, 16#3645, 16#3646,
    16#3730, 16#3731, 16#3732, 16#3733, 16#3734, 16#3735, 16#3736,
    16#3737, 16#3738, 16#3739, 16#3741, 16#3742, 16#3743, 16#3744,
    16#3745, 16#3746, 16#3830, 16#3831, 16#3832, 16#3833, 16#3834,
    16#3835, 16#3836, 16#3837, 16#3838, 16#3839, 16#3841, 16#3842,
    16#3843, 16#3844, 16#3845, 16#3846, 16#3930, 16#3931, 16#3932,
    16#3933, 16#3934, 16#3935, 16#3936, 16#3937, 16#3938, 16#3939,
    16#3941, 16#3942, 16#3943, 16#3944, 16#3945, 16#3946, 16#4130,
    16#4131, 16#4132, 16#4133, 16#4134, 16#4135, 16#4136, 16#4137,
    16#4138, 16#4139, 16#4141, 16#4142, 16#4143, 16#4144, 16#4145,
    16#4146, 16#4230, 16#4231, 16#4232, 16#4233, 16#4234, 16#4235,
    16#4236, 16#4237, 16#4238, 16#4239, 16#4241, 16#4242, 16#4243,
    16#4244, 16#4245, 16#4246, 16#4330, 16#4331, 16#4332, 16#4333,
    16#4334, 16#4335, 16#4336, 16#4337, 16#4338, 16#4339, 16#4341,
    16#4342, 16#4343, 16#4344, 16#4345, 16#4346, 16#4430, 16#4431,
    16#4432, 16#4433, 16#4434, 16#4435, 16#4436, 16#4437, 16#4438,
    16#4439, 16#4441, 16#4442, 16#4443, 16#4444, 16#4445, 16#4446,
    16#4530, 16#4531, 16#4532, 16#4533, 16#4534, 16#4535, 16#4536,
    16#4537, 16#4538, 16#4539, 16#4541, 16#4542, 16#4543, 16#4544,
    16#4545, 16#4546, 16#4630, 16#4631, 16#4632, 16#4633, 16#4634,
    16#4635, 16#4636, 16#4637, 16#4638, 16#4639, 16#4641, 16#4642,
    16#4643, 16#4644, 16#4645, 16#4646}).

    Que realiza 90MB/s en mi notebook i5 CPU M 520 @ 2.40 GHz en las pruebas de 10 MB trozos. Pero optimización fue llevado al extremo. También puede hacer 97MB si el uso de 16bit de búsqueda, pero es loco y demasiado tiempo para publicar aquí.

  2. 7

    La mejora en @hairyhum

    Esto se ocupa de cero rellenos

    << <<Y>> ||<<X:4>> <= Id, Y <- integer_to_list(X,16)>>

    transformación inversa

    <<<<Z>> || <<X:8,Y:8>> <= Id,Z <- [binary_to_integer(<<X,Y>>,16)]>>, %%hex to binary

  3. 4

    Usted podría hacer:
    [ hd(erlang:integer_to_list(Picar, 16)) || << Nibble:4 >> <= Binario ].

    Que devolvería una lista(string) que contiene los dígitos hexadecimales de la binaria. Aunque dudo de la eficacia de esta operación va a tener ningún efecto sobre el tiempo de ejecución de su sistema, usted también podría tener este bin_to_hex función de devolución de un iolist que es más sencillo de construir y se acopla cuando la salida de todos modos. La siguiente función devuelve un iolist con el formato de ejemplo que usted dio:

    bin_to_hex(Bin) when is_binary(Bin) ->
    JoinableLength = byte_size(Bin) - 1,
    << Bytes:JoinableLength/binary, LastNibble1:4, LastNibble2:4 >> = Bin,
    [ "<< ",
    [ [ erlang:integer_to_list(Nibble1, 16), erlang:integer_to_list(Nibble2, 16), ", " ]
    || << Nibble1:4, Nibble2:4 >> <= Bytes ],
    erlang:integer_to_list(LastNibble1, 16),
    erlang:integer_to_list(LastNibble2, 16),
    " >>" ].

    Es un poco feo, pero se ejecuta a través de los binarios de una vez y no recorrer la lista de salida (de lo contrario me hubiera usa cadena:se unen para obtener la intercaladas «, » secuencias). Si esta función no es el bucle interno de algún proceso (tengo un tiempo difícil creer que esta función será su cuello de botella), entonces usted probablemente debería ir con algunos trivialmente menos eficiente, pero mucho más obvio de código como:

    bin_to_hex(Bin) when is_binary(Bin) ->
    "<< " ++ string:join([byte_to_hex(B) || << B >> <= Bin ],", ") ++ " >>".
    byte_to_hex(<< N1:4, N2:4 >>) ->
    [erlang:integer_to_list(N1, 16), erlang:integer_to_list(N2, 16)].
  4. 4

    Este no ha visto ninguna acción durante un tiempo, pero todos los antecedentes las soluciones parecen excesivamente complicado.
    He aquí lo que, para mí, parece mucho más simple:

    [begin if N < 10 -> 48 + N; true -> 87 + N end end || <<N:4>> <= Bin]

    Si lo prefiere ampliado un poco:

    [begin
    if
    N < 10 ->
    48 + N; % 48 = $0
    true ->
    87 + N  % 87 = ($a - 10)
    end
    end || <<N:4>> <= Bin]
  5. 3

    Aquí es otro, cortas y rápidas, versión que yo uso:

    hexlify(Bin) when is_binary(Bin) ->
    << <<(hex(H)),(hex(L))>> || <<H:4,L:4>> <= Bin >>.
    hex(C) when C < 10 -> $0 + C;
    hex(C) -> $a + C - 10.
  6. 2

    si prefiere hacer una cadena binaria en lugar de erlang predeterminada de la lista de cadenas de caracteres, puede utilizar el binario de la comprensión de la sintaxis, como lo hice en mi sha1 la generación de código:

    1> << << if N >= 10 -> N -10 + $a;
    1>          true    -> N     + $0 end >>
    1>    || <<N:4>> <= crypto:hash(sha, "hello world") >>.
    <<"2aae6c35c94fcfb415dbe95f408b9ce91ee846ed">>

    mismo como en python binascii.b2a_hex:

    >>> binascii.b2a_hex(sha.new('hello world').digest())
    '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
  7. 1
    bin_to_hex_list(Bin) when is_binary(Bin) ->
    lists:flatten([integer_to_list(X,16) || <<X>> <= Bin]).
    • Esto no hace ningún cero de relleno, por lo que los resultados son incorrectos. Si los primeros 4 bits de un byte son 0, entonces no dejará de producir un dígito para que de bytes cuando los dos son necesarios.

Dejar respuesta

Please enter your comment!
Please enter your name here