Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / PostgreSQL Новый топик    Ответить
 Получить текст из bytea  [new]
DbDude
Member

Откуда:
Сообщений: 25
В поле content типа bytea сохранен текст HTML-файла.
При попытке преобразовать его в текст выражением content::text первая строка файла выглядит так

<\000!\000D\000O\000C\000T\000Y\000P\000E\000 \000h\000t\000m\000l\000>

А должно быть

<!DOCTYPE html>

То есть появились нули для каждого символа. ! отображается как \000! и т.д..
Как это исправить?
25 окт 21, 00:47    [22387517]     Ответить | Цитировать Сообщить модератору
 Re: Получить текст из bytea  [new]
Swa111
Member

Откуда:
Сообщений: 241
DbDude,

попробуйте так, функции можно будет перенести в public

+
-- convert from bytea, containing UTF-16-BE data
CREATE OR REPLACE FUNCTION pg_temp.convert_from_utf16be(utf16_data bytea, invalid_replacement text DEFAULT '?')
  RETURNS text
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
WITH source(unit) AS (
  SELECT (get_byte(utf16_data, i) << 8) | get_byte(utf16_data, i + 1)
  FROM generate_series(0, octet_length(utf16_data) - 2, 2) i
),
codes(lag, unit, lead) AS (
  SELECT lag(unit, 1) OVER (), unit, lead(unit, 1) OVER ()
  FROM source
)
SELECT string_agg(CASE
  WHEN unit >= 56320 AND unit <= 57343 THEN CASE
    WHEN lag >= 55296 AND lag <= 56319 THEN '' -- already processed
    ELSE invalid_replacement
  END
  WHEN unit >= 55296 AND unit <= 56319 THEN CASE
    WHEN lead >= 56320 AND lead <= 57343 THEN chr((unit << 10) + lead - 56613888)
    ELSE invalid_replacement
  END
  ELSE chr(unit)
END, '')
FROM codes
$function$;

-- convert from bytea, containing UTF-16-LE data
CREATE OR REPLACE FUNCTION pg_temp.convert_from_utf16le(utf16_data bytea, invalid_replacement text DEFAULT '?')
  RETURNS text
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
WITH source(unit) AS (
  SELECT get_byte(utf16_data, i) | (get_byte(utf16_data, i + 1) << 8)
  FROM generate_series(0, octet_length(utf16_data) - 2, 2) i
),
codes(lag, unit, lead) AS (
  SELECT lag(unit, 1) OVER (), unit, lead(unit, 1) OVER ()
  FROM source
)
SELECT string_agg(CASE
  WHEN unit >= 56320 AND unit <= 57343 THEN CASE
    WHEN lag >= 55296 AND lag <= 56319 THEN '' -- already processed
    ELSE invalid_replacement
  END
  WHEN unit >= 55296 AND unit <= 56319 THEN CASE
    WHEN lead >= 56320 AND lead <= 57343 THEN chr((unit << 10) + lead - 56613888)
    ELSE invalid_replacement
  END
  ELSE chr(unit)
END, '')
FROM codes
$function$;

-- convert from bytea, containing UTF-16 data (with or without BOM)
CREATE OR REPLACE FUNCTION pg_temp.convert_from_utf16(utf16_data bytea, invalid_replacement text DEFAULT '?')
  RETURNS text
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT CASE COALESCE(octet_length(utf16_data), 0)
  WHEN 0 THEN ''
  WHEN 1 THEN invalid_replacement
  ELSE CASE substring(utf16_data FOR 2)
    WHEN E'\\xFFFE' THEN pg_temp.convert_from_utf16le(substring(utf16_data FROM 3), invalid_replacement)
    ELSE pg_temp.convert_from_utf16be(substring(utf16_data FROM 3), invalid_replacement)
  END
END
$function$;



select pg_temp.convert_from_utf16be('\000<\000!\000D\000O\000C\000T\000Y\000P\000E\000 \000h\000t\000m\000l\000>'::bytea,'?')
25 окт 21, 13:04    [22387662]     Ответить | Цитировать Сообщить модератору
 Re: Получить текст из bytea  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 54789
DbDude
То есть появились нули для каждого символа. ! отображается как \000! и т.д..

Это только отображение в результате перевода в текст. Смотрите настоящее содержимое, в байтах.
25 окт 21, 13:35    [22387697]     Ответить | Цитировать Сообщить модератору
 Re: Получить текст из bytea  [new]
DbDude
Member

Откуда:
Сообщений: 25
Swa111,
К сожалению работает не очень быстро.
Но другого способа я не нашел.
Спасибо.
26 окт 21, 18:36    [22388449]     Ответить | Цитировать Сообщить модератору
 Re: Получить текст из bytea  [new]
DbDude
Member

Откуда:
Сообщений: 25
Dimitry Sibiryakov,

Нужно
1) определить, что там за кодировка
2) преобразовать содержимое в читаемый текст
26 окт 21, 18:38    [22388451]     Ответить | Цитировать Сообщить модератору
 Re: Получить текст из bytea  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 54789
Да. Для этого:
1) Посмотреть на содержимое в виде байт;
2) Применить правильный способ отображения.

Подсказываю: некоторые приложения способны правильно отображать UTF-16 без каких-либо дополнительных преобразований.
27 окт 21, 13:37    [22388749]     Ответить | Цитировать Сообщить модератору
Все форумы / PostgreSQL Ответить