new String(byte[]) дает разные результаты, когда я помещаю его в vs pull из базы данных

Прежде чем я сохраню байтовый массив в базе данных, если я распечатаю вывод new String(data) он возвращает читаемую строку, например "foobar", но после того, как я вытащил ее из базы данных, new String(data) будет читаться как куча тарабарщины вроде "9238929384739427349327...". Здесь так много частей, что я просто попытаюсь перечислить их все. Я использую eclipselink, и мой столбец данных определен:

@Lob
@Column(name = "data")
private byte[] data;

Если я запускаю этот код:

public static void main(String[] args) {
    System.out.println(Charset.defaultCharset());
}

Выводит windows-1250,

Моя база данных определяется как:

CREATE DATABASE project_trunk
  WITH OWNER = project
       ENCODING = 'UTF8'
       TABLESPACE = pg_default
       LC_COLLATE = 'English_United States.1252'
       LC_CTYPE = 'English_United States.1252'
       CONNECTION LIMIT = -1;

Я также пробовал это на БД, определенной так:

CREATE DATABASE project_trunk
  WITH OWNER = project
       ENCODING = 'UTF8'
       TABLESPACE = pg_default
       LC_COLLATE = 'en_US.UTF-8'
       LC_CTYPE = 'en_US.UTF-8'
       CONNECTION LIMIT = -1;

И проблема все еще возникает.

Я думаю, что происходит, потому что моя база данных отличается от моего сервера приложений. Когда я помещаю вещи в базу данных и вынимаю их снова, она декодирует их неправильно, поэтому это выглядит как бред. Я на что-то там?

Теперь, когда дело доходит до решения этой проблемы, я немного запутался. Я думаю, что мне следует изменить кодировку файла моего сервера приложений, чтобы она соответствовала базе данных. Я использую Glassfish 2.1.1. Когда я иду в application server -> advanced -> domain attributes и установите Locale в "UTF8" или "UTF-8", это говорит мне, что требуется перезагрузка. После перезапуска Glassfish это поле остается пустым, и я все еще получаю ошибку. Я думаю, может быть, это не спасает собственность. Я бы вручную поместил его в файл конфигурации, но я не знаю, куда и что поместить.

В качестве альтернативы я попытался создать свою базу данных с ENCODING = 'WIN1250', но когда я это сделал, он сказал, что мой LC_CTYPE должен быть "WIN1252". Когда я устанавливаю LC_CTYPE в "WIN1252", он говорит, что кодировка не существует.


Я трачу много времени на это, я хотел бы знать, если я что-то здесь. Верна ли моя теория "несинхронизированных кодировок между appserver и db", или я гоняюсь за красной сельдью? Если бы кто-нибудь мог помочь мне понять, как изменить этот параметр для glassfish 2.1.1, это также было бы очень полезно. Спасибо

РЕДАКТИРОВАТЬ: Люди спрашивают, почему я храню строки в виде сырых байтов. Это не совсем то, что я делаю, иногда необработанные байты представляют изображение, PDF или двоичный файл, иногда это текст. Мой тест вставляет простой текстовый String и вытаскивает его обратно, чтобы убедиться, что он был сохранен правильно. Этот тест проходит на нашем CI сервере, который находится на Linux.

EDIT2: меня попросили показать необработанный двоичный ввод против необработанного двоичного вывода.

Ожидаемые:[116, 104, 105, 115, 32, 105, 115, 32, 109, 121, 32, 97, 116, 116, 97, 99, 104, 109, 101, 110, 116, 32, 97, 115, 32, 97, 32, 83, 116, 114, 105, 110, 103]

Актуально:[60, 54, 56, 54, 57, 55, 51, 50, 48, 54, 57, 55, 51, 50, 48, 54, 100, 55, 57, 50, 48, 54, 49, 55, 52, 55, 52, 54, 49, 54, 51, 54, 56, 54, 100, 54, 53, 54, 101, 55, 52, 50, 48, 54, 49, 55, 51, 50, 48, 54, 49, 50, 48, 53, 51, 55, 52, 55, 50, 54, 57, 54, 101, 54, 55]

Я дал тот же самый тест, который проверяет байты моему коллеге, который работает на Mac, и это проходит для него.

2 ответа

Решение

иногда необработанные байты представляют изображение или PDF или двоичный файл, иногда это текст

Хорошо, тогда вы не должны хранить их как текст.

Независимо от того, что в настоящее время идет не так, даже если вы можете заставить это работать для данных, которые на самом деле являются текстовыми, у вас возникнут проблемы позже.

Если вы должны хранить произвольные двоичные данные в виде текста, вы должны использовать base64 для их кодирования - таким образом, вы можете без проблем вернуться к исходному двоичному файлу. (Вам нужно только иметь возможность транспортировать строки ASCII, и это обычно достаточно просто.) Для Base64 существует множество сторонних библиотек; Мне нравится этот автономный публичный домен.

В качестве альтернативы, сохраните данные в виде двоичных данных в базе данных, например, используя поле bytea тип данных. Таким образом, вам не нужно выполнять какие-либо преобразования: вы должны просто иметь возможность поместить их в базу данных в виде байтового массива и вывести в виде байтового массива.

РЕДАКТИРОВАТЬ: Хорошо, похоже, вы получаете обратно шестнадцатеричное представление двоичных данных, но в ASCII. Это явно странно.

Оказывается, это вызвано тем, что PostgreSQL работает в версии 9 против версии 8. Большинство моих коллег использовали версию 8, но я недавно получил новый компьютер, поэтому я использовал последнюю версию PostgreSQL.

Вам нужно установить output_bytea в "escape".

Получение почти удвоенной длины при чтении байта [] из postgres с помощью jpa

Хотя я не нашел там достаточного ответа, но нашел его в списке рассылки, и он решил мою проблему: http://www.postgresql.org/message-id/AANLkTikkE-jQ9srZ9VL1JuJ5h=UCutx8ZLim+OfQ1T4z@mail.gmail.com

Уважаемый список,

Недавнее изменение формата bytea_output с escape на hex в 9.0, по-видимому, нарушает популярные постоянные модули обработки сеансов, такие как Apache::Session::Postgres, который хранит протравленные структуры данных в столбцах bytea таблицы db. Трудно угадать первопричину из исключения, сгенерированного упомянутым модулем. Проблема исправлена ​​добавлением bytea_output='escape' в postgresql.conf и выдачей перезагрузки pg_ctl.

Например, в приложении RT ошибка: error: RT не может сохранить ваш сеанс. Это может означать, что каталог /blah/blah/foo/bar недоступен для записи или таблица базы данных отсутствует или повреждена

Редж Раджеш Кумар Малла.

Другие вопросы по тегам