将bytea转换为二进制字符串

时间:2019-05-06 14:33:15

标签: postgresql binary-data bytea

我需要解码base64字符串并获取二进制文件的一部分。

Postgres中是否有SQL函数可以将bytea转换为二进制字符串表示形式?
(例如“ 00010001010101010” 。)

2 个答案:

答案 0 :(得分:1)

demo:db<>fiddle

您可以将以下代码放入函数中:

WITH byte AS (   -- 1
    SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
    string_agg(      -- 5
        get_byte(value, gs)::bit(8)::text -- 4
        , ''
    )
FROM 
    byte,
    generate_series(        -- 3
        0, 
        length(value) - 1   -- 2
    ) gs

我在小提琴中演示了查询的发展。

  1. WITH子句封装了bytea值,以便在进一步的代码中重复使用
  2. length()计算bytea值的二进制长度
  3. generate_series()创建一个从0length - 1(在我的示例中为0 - 3)的列表
  4. get_byte()第二次获取bytea值,并给出位置gs处的字节(先前的计算值0-3)。这给出了字节的integer表示形式。之后,将类型转换为bit(8)会将此函数的结果转换为其二进制表示形式(1字节= 8位)
  5. string_agg()最后将所有二进制字符串汇总为一个。 (采用其text表示形式代替bit类型,没有分隔符)

一个函数可能看起来像这样:

CREATE OR REPLACE FUNCTION to_bit(value bytea) RETURNS SETOF text AS 
$$
BEGIN
    RETURN QUERY 
        SELECT
            string_agg(get_byte(value, gs)::bit(8)::text, '')
        FROM 
            generate_series(0, length(value) - 1) gs;
END;
$$ LANGUAGE plpgsql;

之后,您可以将其命名为:

SELECT to_bit(E'\\xDEADBEEF'::bytea)

您可以使用get_bit()而不是get_byte()进行尝试。这样可以确保::bit(8)的使用安全,但是当然您需要将长度乘以因子8

生成的位字符串具有另一个位顺序,但也许更适合您的用例:

WITH byte AS (
    SELECT E'\\xDEADBEEF'::bytea as value
)
SELECT
    string_agg(get_bit(value, gs)::text, '')
FROM 
    byte,
    generate_series(0, length(value) * 8 - 1) gs

demo:db<>fiddle

答案 1 :(得分:1)

假设您的Postgres安装以bytea_output的默认设置hex运行,有一个非常简单的技巧:

SELECT right((bytea '\xDEADBEEF')::text, -1)::varbit

结果:

'11011110101011011011111011101111'

right(text, -1)只是从文本表示中删除前导反斜杠的最便宜方法。

varbit(或其在标准SQL中的正式名称:bit varying)用于任意长度的位st。如果需要,将结果转换为textvarchar

相关,并附有说明: