如何在不知道原始类型的情况下将缓冲区转换为 string/number/date
How to convert a buffer to string/number/date without knowing the original type
我正在编写连接到 HBase 并支持不同 GET/POST 查询的查询服务。检索到的数据是一个对象数组,其中键是列的名称,值是 buffer。
但是,对象的每一列的简单 columns[columnName].toString()
不起作用,因为有些字段可以是字符串、日期或数字。 .toString
适用于 string/date,但数字 return 格式如下:"all": "\u0000\u0000\u0000\u0000\u0000\u0000\u0004\ufffd",
.
蛮力(我确实意识到这不是我正在测试的漂亮代码)方法是这样的:
function parseEntry(entry) {
let parsed = {};
Object.keys(entry.columns).forEach(column => {
const value = entry.columns[column].value;
parsed[column] = (typeof value === 'object' && value.length <= 8) ?
value.readInt32BE(4) :
value.toString();
});
return parsed;
}
但有时我得到长度为 < 8
的字符串,我会尝试将它们转换为数字,这是不希望的行为。我还尝试使用 /[^\u0000-\uffff]+/.test(value)
之类的正则表达式来测试该值,但出于某种原因,每个条目的测试 return 都为 false。
我尝试了 .toString
、JSON.parse
、.trim
、readInt32BE
等所有可能的组合,但我没有成功地正确解析这样的对象。有没有一种方法可以在没有很多基于列名称的 if 条件的情况下正确地做到这一点?
编辑:
我的响应数组中的一个条目看起来像这样(如果它可以帮助您进行测试;出于安全目的,我删除了一些字段;all
应该是一个数字,cUS
和 fs
应该是日期, fqdn
是一个字符串,val
是一个 IP,也是一个字符串。
{ 'd:all':
{ value: <Buffer 00 00 00 00 00 00 04 8e>,
timestamp: [Int64 value:1553606385109 octets:00 00 01 69 ba 28 1d d5] },
'd:cUS':
{ value: <Buffer 32 30 31 39 2d 30 33 2d 32 36 54 31 32 3a 35 36 3a 30 39 2e 31 37 37 5a>,
timestamp: [Int64 value:1553604980146 octets:00 00 01 69 ba 12 ad b2] },
'd:fqdn':
{ value: <Buffer 61 70 69 2d 67 6c 6f 62 61 6c 2e 6e 65 74 66 6c 69 78 2e 63 6f 6d>,
timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
'd:fs':
{ value: <Buffer 32 30 31 39 2d 30 33 2d 32 32 54 31 35 3a 30 30 3a 31 33 2e 35 30 32 5a>,
timestamp: [Int64 value:9005645987910764 octets:00 1f fe 96 5a 15 14 6c] },
'd:val':
{ value: <Buffer 35 32 2e 32 30 39 2e 31 33 30 2e 31 37 32>,
timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
}
您可以使用以下方法将字符串转换为数字。 \u0000
代表一个字符,所以你只需要使用 .
来匹配它。然后使用 String#charCodeAt 您可以将其转换为数字。
The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.
const res = "\u0000\u0000\u0000\u0000\u0000\u0000\u0004\ufffd"
.match(/./g)
.map(v=>v.charCodeAt());
console.log(res);
但一般来说,您需要条件来检查您应该使用什么方法来转换缓冲区。
这可以通过 Buffer 包来完成,方法是将类型(十六进制、二进制、utf8(默认)或 ascii)作为参数传递。
我正在编写连接到 HBase 并支持不同 GET/POST 查询的查询服务。检索到的数据是一个对象数组,其中键是列的名称,值是 buffer。
但是,对象的每一列的简单 columns[columnName].toString()
不起作用,因为有些字段可以是字符串、日期或数字。 .toString
适用于 string/date,但数字 return 格式如下:"all": "\u0000\u0000\u0000\u0000\u0000\u0000\u0004\ufffd",
.
蛮力(我确实意识到这不是我正在测试的漂亮代码)方法是这样的:
function parseEntry(entry) {
let parsed = {};
Object.keys(entry.columns).forEach(column => {
const value = entry.columns[column].value;
parsed[column] = (typeof value === 'object' && value.length <= 8) ?
value.readInt32BE(4) :
value.toString();
});
return parsed;
}
但有时我得到长度为 < 8
的字符串,我会尝试将它们转换为数字,这是不希望的行为。我还尝试使用 /[^\u0000-\uffff]+/.test(value)
之类的正则表达式来测试该值,但出于某种原因,每个条目的测试 return 都为 false。
我尝试了 .toString
、JSON.parse
、.trim
、readInt32BE
等所有可能的组合,但我没有成功地正确解析这样的对象。有没有一种方法可以在没有很多基于列名称的 if 条件的情况下正确地做到这一点?
编辑:
我的响应数组中的一个条目看起来像这样(如果它可以帮助您进行测试;出于安全目的,我删除了一些字段;all
应该是一个数字,cUS
和 fs
应该是日期, fqdn
是一个字符串,val
是一个 IP,也是一个字符串。
{ 'd:all':
{ value: <Buffer 00 00 00 00 00 00 04 8e>,
timestamp: [Int64 value:1553606385109 octets:00 00 01 69 ba 28 1d d5] },
'd:cUS':
{ value: <Buffer 32 30 31 39 2d 30 33 2d 32 36 54 31 32 3a 35 36 3a 30 39 2e 31 37 37 5a>,
timestamp: [Int64 value:1553604980146 octets:00 00 01 69 ba 12 ad b2] },
'd:fqdn':
{ value: <Buffer 61 70 69 2d 67 6c 6f 62 61 6c 2e 6e 65 74 66 6c 69 78 2e 63 6f 6d>,
timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
'd:fs':
{ value: <Buffer 32 30 31 39 2d 30 33 2d 32 32 54 31 35 3a 30 30 3a 31 33 2e 35 30 32 5a>,
timestamp: [Int64 value:9005645987910764 octets:00 1f fe 96 5a 15 14 6c] },
'd:val':
{ value: <Buffer 35 32 2e 32 30 39 2e 31 33 30 2e 31 37 32>,
timestamp: [Int64 value:1553606699454 octets:00 00 01 69 ba 2c e9 be] },
}
您可以使用以下方法将字符串转换为数字。 \u0000
代表一个字符,所以你只需要使用 .
来匹配它。然后使用 String#charCodeAt 您可以将其转换为数字。
The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 code unit at the given index.
const res = "\u0000\u0000\u0000\u0000\u0000\u0000\u0004\ufffd"
.match(/./g)
.map(v=>v.charCodeAt());
console.log(res);
但一般来说,您需要条件来检查您应该使用什么方法来转换缓冲区。
这可以通过 Buffer 包来完成,方法是将类型(十六进制、二进制、utf8(默认)或 ascii)作为参数传递。