Erlang Elixir解析二进制数据?
例如: 我有一个二进制代码,如下所示:Erlang Elixir解析二进制数据?,erlang,elixir,Erlang,Elixir,例如: 我有一个二进制代码,如下所示: bin1 = "2\nok\n3\nbcd\n\n" 或 等等 格式是 byte_size \n bytes \n byte_size \n bytes \n \n 我想要一个解析二进制文件 ["ok", "bcd"] 如何在Elixir或Erlang中实现 围棋版 一个围棋版本可以解析这个 func (c *Client) parse() []string { resp := []string{} buf :
bin1 = "2\nok\n3\nbcd\n\n"
或
等等
格式是
byte_size \n bytes \n byte_size \n bytes \n \n
我想要一个解析二进制文件
["ok", "bcd"]
如何在Elixir或Erlang中实现
围棋版
一个围棋版本可以解析这个
func (c *Client) parse() []string {
resp := []string{}
buf := c.recv_buf.Bytes()
var idx, offset int
idx = 0
offset = 0
for {
idx = bytes.IndexByte(buf[offset:], '\n')
if idx == -1 {
break
}
p := buf[offset : offset+idx]
offset += idx + 1
//fmt.Printf("> [%s]\n", p);
if len(p) == 0 || (len(p) == 1 && p[0] == '\r') {
if len(resp) == 0 {
continue
} else {
c.recv_buf.Next(offset)
return resp
}
}
size, err := strconv.Atoi(string(p))
if err != nil || size < 0 {
return nil
}
if offset+size >= c.recv_buf.Len() {
break
}
v := buf[offset : offset+size]
resp = append(resp, string(v))
offset += size + 1
}
return []string{}
}
func(c*客户端)parse()[]字符串{
resp:=[]字符串{}
buf:=c.recv_buf.Bytes()
变量idx,偏移量int
idx=0
偏移量=0
为了{
idx=bytes.IndexByte(buf[offset:],'\n')
如果idx==-1{
打破
}
p:=buf[偏移量:偏移量+idx]
偏移量+=idx+1
//fmt.Printf(“>[%s]\n”,p);
如果len(p)==0 | |(len(p)==1&&p[0]='\r'){
如果len(resp)=0{
持续
}否则{
c、 记录下一步(偏移量)
返回响应
}
}
大小,错误:=strconv.Atoi(字符串(p))
如果err!=nil | | size<0{
归零
}
如果偏移量+大小>=c.recv_buf.Len(){
打破
}
v:=buf[偏移量:偏移量+大小]
resp=append(resp,string(v))
偏移量+=大小+1
}
返回[]字符串{}
}
感谢更灵活的解决方案:
result = bin
|> String.split("\n")
|> Stream.chunk(2)
|> Stream.map(&parse_bytes/1)
|> Enum.filter(fn s -> s != "" end)
def parse_bytes(["", ""]), do: ""
def parse_bytes([byte_size, bytes]) do
byte_size_int = byte_size |> String.to_integer
<<parsed :: binary-size(byte_size_int)>> = bytes
parsed
end
defp parse("\n") do
[]
end
defp parse(data) do
{offset, _} = :binary.match(data, "\n")
size = String.to_integer(binary_part(data, 0, offset))
value = binary_part(data, offset + 1, size)
len = offset + 1 + size + 1
[value] ++ parse(binary_part(data, len, byte_size(data) - len))
end
result=bin
|>String.split(“\n”)
|>Stream.chunk(2)
|>Stream.map(&parse_bytes/1)
|>枚举过滤器(fn s->s!=“”结束)
def parse_字节([“”,“”),do:“
def parse_字节([字节大小,字节])do
byte_size_int=byte_size|>String.to_integer
=字节
解析
结束
我写了一个解决方案:
result = bin
|> String.split("\n")
|> Stream.chunk(2)
|> Stream.map(&parse_bytes/1)
|> Enum.filter(fn s -> s != "" end)
def parse_bytes(["", ""]), do: ""
def parse_bytes([byte_size, bytes]) do
byte_size_int = byte_size |> String.to_integer
<<parsed :: binary-size(byte_size_int)>> = bytes
parsed
end
defp parse("\n") do
[]
end
defp parse(data) do
{offset, _} = :binary.match(data, "\n")
size = String.to_integer(binary_part(data, 0, offset))
value = binary_part(data, offset + 1, size)
len = offset + 1 + size + 1
[value] ++ parse(binary_part(data, len, byte_size(data) - len))
end
Elixir邮件列表提供了另一个:
defp parse_binary("\n"), do: []
defp parse_binary(binary) do
{size, "\n" <> rest} = Integer.parse(binary)
<<chunk :: [binary, size(size)], "\n", rest :: binary>> = rest
[chunk|parse_binary(rest)]
end
defp parse_binary(“\n”),do:[]
defp parse_二进制(二进制)do
{size,“\n”rest}=Integer.parse(二进制)
=休息
[chunk | parse_binary(rest)]
结束
谢谢,我添加了一个版本来描述这个问题。请注意,这个解决方案不适合解析大量数据,因为它会迭代多次。李大双回答中的第二个解决方案可以避免这个问题。我已经更新了我的解决方案,使用流
函数,而不是枚举
。这也将避免多次迭代问题。请注意,在较新的elixir版本中,您必须编写二进制大小(byte\u size\u int)
,而不是[二进制大小(byte\u size\u int)]