MessagePack 是否允许填充整数?
Does MessagePack allow padded integers?
我正在尝试使用 MessagePack 在 Erlang 和 Java 中序列化整数。
在 Java 中,我可以用任意数量的 0 填充一个包含一个整数的数组,并且 MessagePack.read()
仍然是 returns 正确的值。但是在 Erlang 中,如果有任何额外的零,msgpack:unpack/1
会失败。
例如,msgpack:unpack/1
通过 <<10>>
按预期工作 returns {ok,10}
。但是添加额外的零并传递 <<10,0,0>>
失败,返回 {error,not_just_binary}
。 API 中的注释指出错误意味着术语已被解码但二进制仍然存在。
当我浏览 Erlang API 的源代码以获取更多信息来问这个问题时,我注意到另一个函数,msgpack:unpack_stream/1
,其中 returns 一个元组,第一个解码术语,与无关的二进制文件配对,而不是返回错误。这更符合 Java 中的 read
。
但我还是想知道是否有更好的方法来解决这个问题,比如使用固定长度类型的方法。
库 msgpack 不是用来解码原始二进制文件的,而是用来解码以前用 msgpack:pack.
编码的二进制文件的
原因是二进制文件本身没有结构,因此您必须在其中包含一些信息才能进行解码。这就是像 term_to_binary 这样的函数所做的,使用 erlang 外部格式:
1> B = term_to_binary({12,atom,[$a,$l,$i,$s,$t]}).
<<131,104,3,97,12,100,0,4,97,116,111,109,107,0,5,97,108,
105,115,116>>
2> binary_to_term(B).
{12,atom,"alist"}
库 msgpack 允许使用其他编码方法。
来解决你的问题。 unpack 和 unpack_stream 之间的区别在于,第一个期望二进制文件中有一个编码项,而第二个假设尾随二进制文件包含其他编码项。
当你调用msgpack:unpack(<<10>>)
时,它属于第一个元素小于128的情况:在这种情况下,编码值就是值本身。如果您尝试使用大于 127 的值,则会出现错误:
4> msgpack:unpack(<<10>>).
{ok,10}
5> msgpack:unpack(<<200>>).
{error,incomplete}
6>
当您调用 msgpack:unpack_stream(<<10>>)
时,它的作用完全相同,因此第一个元素被解码,结果为 10,其余二进制文件用于进一步解码:
8> {A,Rest} = msgpack:unpack_stream(<<10,0>>).
{10,<<0>>}
9> msgpack:unpack_stream(Rest).
{0,<<>>}
10> msgpack:unpack_stream(<<200,0>>).
{error,incomplete}
11> msgpack:unpack_stream(<<200,0,0>>).
{error,incomplete}
12> msgpack:unpack_stream(<<200,0,0,0>>).
{error,{badarg,{bad_ext,200}}}
13>
使用该库的正确方法是先对您的消息进行编码:
13> Msg = msgpack:pack(<<10,0,0>>).
<<163,10,0,0>>
14> msgpack:unpack(Msg).
{ok,<<10,0,0>>}
或者第一个例子:
24> Msg1 = msgpack:pack(msgpack:term_to_binary({12,atom,[$a,$l,$i,$s,$t]})).
<<183,199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>
25> {ok,Rep1} = msgpack:unpack(Msg1).
{ok,<<199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>}
26> msgpack:binary_to_term(Rep1).
{12,atom,"alist"}
27>
[编辑]
这是一个添加填充和检测它的解包器的提议。它使用 unpack_stream,因为不可能修改整数的编码方式。
Packer = fun(X, Opt) -> {ok, {12,<<>>}} end,
Unpacker = fun(12, _) -> {ok, padding} end,
Opt = [{ext,{Packer,Unpacker}}],
Pad = fun(B) -> Size = 10 - size(B), SB = Size*8,<<B/binary,16#C7,Size,12,0:SB>> end,
R = msgpack:pack(256897),
Var = Pad(R),
{I,Rest} = msgpack:unpack_stream(Var,Opt),
{padding,<<>>} = msgpack:unpack_stream(Rest,Opt).
我正在尝试使用 MessagePack 在 Erlang 和 Java 中序列化整数。
在 Java 中,我可以用任意数量的 0 填充一个包含一个整数的数组,并且 MessagePack.read()
仍然是 returns 正确的值。但是在 Erlang 中,如果有任何额外的零,msgpack:unpack/1
会失败。
例如,msgpack:unpack/1
通过 <<10>>
按预期工作 returns {ok,10}
。但是添加额外的零并传递 <<10,0,0>>
失败,返回 {error,not_just_binary}
。 API 中的注释指出错误意味着术语已被解码但二进制仍然存在。
当我浏览 Erlang API 的源代码以获取更多信息来问这个问题时,我注意到另一个函数,msgpack:unpack_stream/1
,其中 returns 一个元组,第一个解码术语,与无关的二进制文件配对,而不是返回错误。这更符合 Java 中的 read
。
但我还是想知道是否有更好的方法来解决这个问题,比如使用固定长度类型的方法。
库 msgpack 不是用来解码原始二进制文件的,而是用来解码以前用 msgpack:pack.
编码的二进制文件的原因是二进制文件本身没有结构,因此您必须在其中包含一些信息才能进行解码。这就是像 term_to_binary 这样的函数所做的,使用 erlang 外部格式:
1> B = term_to_binary({12,atom,[$a,$l,$i,$s,$t]}).
<<131,104,3,97,12,100,0,4,97,116,111,109,107,0,5,97,108,
105,115,116>>
2> binary_to_term(B).
{12,atom,"alist"}
库 msgpack 允许使用其他编码方法。
来解决你的问题。 unpack 和 unpack_stream 之间的区别在于,第一个期望二进制文件中有一个编码项,而第二个假设尾随二进制文件包含其他编码项。
当你调用msgpack:unpack(<<10>>)
时,它属于第一个元素小于128的情况:在这种情况下,编码值就是值本身。如果您尝试使用大于 127 的值,则会出现错误:
4> msgpack:unpack(<<10>>).
{ok,10}
5> msgpack:unpack(<<200>>).
{error,incomplete}
6>
当您调用 msgpack:unpack_stream(<<10>>)
时,它的作用完全相同,因此第一个元素被解码,结果为 10,其余二进制文件用于进一步解码:
8> {A,Rest} = msgpack:unpack_stream(<<10,0>>).
{10,<<0>>}
9> msgpack:unpack_stream(Rest).
{0,<<>>}
10> msgpack:unpack_stream(<<200,0>>).
{error,incomplete}
11> msgpack:unpack_stream(<<200,0,0>>).
{error,incomplete}
12> msgpack:unpack_stream(<<200,0,0,0>>).
{error,{badarg,{bad_ext,200}}}
13>
使用该库的正确方法是先对您的消息进行编码:
13> Msg = msgpack:pack(<<10,0,0>>).
<<163,10,0,0>>
14> msgpack:unpack(Msg).
{ok,<<10,0,0>>}
或者第一个例子:
24> Msg1 = msgpack:pack(msgpack:term_to_binary({12,atom,[$a,$l,$i,$s,$t]})).
<<183,199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>
25> {ok,Rep1} = msgpack:unpack(Msg1).
{ok,<<199,20,131,131,104,3,97,12,100,0,4,97,116,111,109,
107,0,5,97,108,105,115,116>>}
26> msgpack:binary_to_term(Rep1).
{12,atom,"alist"}
27>
[编辑]
这是一个添加填充和检测它的解包器的提议。它使用 unpack_stream,因为不可能修改整数的编码方式。
Packer = fun(X, Opt) -> {ok, {12,<<>>}} end,
Unpacker = fun(12, _) -> {ok, padding} end,
Opt = [{ext,{Packer,Unpacker}}],
Pad = fun(B) -> Size = 10 - size(B), SB = Size*8,<<B/binary,16#C7,Size,12,0:SB>> end,
R = msgpack:pack(256897),
Var = Pad(R),
{I,Rest} = msgpack:unpack_stream(Var,Opt),
{padding,<<>>} = msgpack:unpack_stream(Rest,Opt).