在SQL中将VARBINARY类型的负载转换为VARCHAR类型

3

我正在尝试将以下有效负载转换为可读字符串。

这是一个包含信息的日志,我想在之后使用它来进行分析和处理。

这是有效负载消息:

0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256

我知道该协议的内容如下:

Header: 3 bytes
ID: 4 bytes
Length: 2 bytes
LogDebug: 1 byte
LogData: N
Timestamp: 6 bytes
CS: 1 byte

我尝试使用:

CONVERT(VARCHAR(MAX), SUBSTRING(payload, 0, 3) + SUBSTRING(payload, 3, 4) + ...)

但是我无法使其工作。我在SSMS文档中看到,SUBSTRING只接受一些数据类型来处理payload,例如字符、二进制、文本、ntext或图像。

我尝试过

CONVERT(VARCHAR(MAX), (SUBSTRING(CONVERT(BINARY,Payload),0, 3)) + (SUBSTRING(CONVERT(BINARY,Payload),3, 4)))

但是尝试了很多方法都没有成功 :(

有什么建议吗?

编辑: 预期的日志应该如下所示:

000:  2016/07/13 00:04:02, (0x71)U2H.LOGDEBUG - Class: a :: AsimovFacade.call() refresh {token=e04ff71b-3be4-486c-b39b-6cc7b9cedb69}

我理解:

#DS

你有收到任何错误信息吗? - jim
没有错误信息,但输出太短了。我知道输出应该是什么。 - Ko Ga
发布与编程有关的内容。仅返回已翻译的文本:请提供预期输出的示例和您得到的错误输出 - Paolo
由于ASCII中字符0(零)的值为0x30,因此您不应该在二进制值的一端看到303030吗? (Unicode对于单个零是0030。)是否有一些数据不是字符,例如两个字节的“长度”是16位整数? - HABO
@HABO,不确定为什么...这就是我在这里的原因 :) - Ko Ga
显示剩余2条评论
2个回答

1

对于 varbinary,Substring 可以正常工作并返回 varbinary。

看起来数据长度字段除了 LogData 长度之外还包括最后 2 个字段。

您的输入中未出现字符串 U2H.LOGDEBUG

declare @b varbinary(max) = 0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256

select cast(substring(@b, 1, 3) as char(3)) as hdr
select cast(substring(@b, 4, 4) as int) as id

-- store length of the payload
declare @len int = cast(substring(@b, 8, 2) as int)
select @len as length

select cast(substring(@b, 10, 1) as binary(1)) as logdebug

-- read payload for the read length, less 7 bytes for the timestamp & cs
select cast(substring(@b, 11, @len - 7) as varchar(max)) as logdata

-- read past payload for 6 bytes for the timestamp (whatever format that is - not epoch)
select substring(@b, @len + 11 - 7, 6) as timestamp

select substring(@b, @len + 11 - 7 + 6, 1) as cs

对于

hdr
----
#DS


id
-----------
7000771


length
-----------
91


logdebug
--------
0x71


logdata
----
Class: a :: AsimovFacade.call() refresh {token=e04ff71b-3be4-486c-b39b-6cc7b9cedb69}


timestamp
----
0x10070D020402


cs
----
0x56

0
尝试使用下面的代码。您基本上只需要将varbinary子字符串转换为协议中的字段,然后转换为适当的类型。
我假设您的4字节ID是一个 int ,并且似乎您的长度字段包括最后的时间戳和“cs”字段,因此您需要从该值中减去7。
DECLARE @payload varbinary(MAX) = 0x234453006AD2C3005B71436C6173733A2061203A3A204173696D6F764661636164652E63616C6C28292072656672657368207B746F6B656E3D65303466663731622D336265342D343836632D623339622D3663633762396365646236397D10070D02040256

DECLARE @header char(3),
        @id     int,
        @length smallint,
        @logdebug char(1),
        @logdata    varchar(MAX),
        @timestamp  char(6),
        @cs         char(1)

SET @header = convert(char(3), substring(@payload, 1, 3))
SET @id = convert(int, substring(@payload, 4, 4))
SET @length = convert(smallint, substring(@payload, 8, 2)) - 7
SET @logdebug = convert(char(1), substring(@payload, 10, 1))
SET @logdata = convert(varchar(MAX), substring(@payload, 11, @length))
SET @timestamp = convert(char(6), substring(@payload, @length + 11, 6))
SET @cs = convert(char(1), substring(@payload, @length + 17, 1))



SELECT @header,@id,@length, @logdebug, @logdata, @timestamp, @cs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接