СИТУАЦИЯ :

Заранее извините, если этот вопрос уже был задан, но решения у меня не работают.

Что бы я ни пытался, я не могу сохранить смайлы в своей базе данных. Они сохраняются как ????.
Единственные правильно сохраненные смайлы - это те, которые требуют всего 3 байта, например, застенчивое лицо или солнце.

Фактический utf8mb4 не работает.

Database screenshot

Он был протестирован как на Android, так и на iOS. С такими же результатами.

ВЕРСИИ :

MySQL: 5.5.49
CodeIgniter: 3.0.0

ШАГИ :

  1. Я изменил набор символов базы данных и свойства сопоставления.

    ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci

  2. Я изменил набор символов таблицы и свойства сопоставления.

    ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  3. Я установил каждое поле таблицы, где это возможно, как Кодировку: UTF-8(ut8mb4) и Сопоставление: utf8mb4_unicode_ci

  4. Я изменил соединение с базой данных в приложении CodeIgniter.

  5. Я выполнил следующее: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci

  6. Наконец, я также пробовал это: REPAIR TABLE table_name; OPTIMIZE TABLE table_name;

Все должно было быть настроено правильно, но это не работает.

НАСТРОЙКИ БАЗЫ ДАННЫХ :

Это результат выполнения следующей команды:

`SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';`

Database settings

НАСТРОЙКИ ТАБЛИЦЫ :

Скриншот структуры таблицы:

Table settings

ПОДКЛЮЧЕНИЕ БАЗЫ ДАННЫХ :

Это настройки подключения к базе данных внутри database.php (обратите внимание, что это не единственная база данных, есть также другие, которые подключаются с использованием utf8)

$db['my_database'] = array(
        'dsn'           => '',
        'hostname'      => PROJECT_DATABASE_HOSTNAME,
        'username'      => PROJECT_DATABASE_USERNAME,
        'password'      => PROJECT_DATABASE_PASSWORD,
        'database'      => PROJECT_DATABASE_NAME,
        'dbdriver'      => 'mysqli',
        'dbprefix'      => '',
        'pconnect'      => FALSE,
        'db_debug'      => TRUE,
        'cache_on'      => FALSE,
        'cachedir'      => '',
        'char_set'      => 'utf8mb4',
        'dbcollat'      => 'utf8mb4_unicode_ci',
        'swap_pre'      => '',
        'encrypt'       => FALSE,
        'compress'      => FALSE,
        'stricton'      => FALSE,
        'failover'      => array(),
        'save_queries'  => TRUE
    );

НАСТРОЙКИ MY.CNF :

Это все содержимое файла my.cnf:

[mysqld]
default-storage-engine=MyISAM
innodb_file_per_table=1
max_allowed_packet=268435456
open_files_limit=10000
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

ВОПРОС :

Вы знаете, почему не работает? Я что-то упускаю?

ГИПОТЕЗА 1 :

Я не уверен, но причина проблемы может быть в следующем:

Как вы можете видеть в my.cnf, character-set-server явно задан как utf8mb4:

Но после выполнения запроса в базе данных:

SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';

В результате character-set-server = latin1

Вы знаете почему? Почему собственно не обновляется?

ГИПОТЕЗА 2 :

Приложение использует несколько разных баз данных. Для этого установлено значение utf8mb4, но для всех остальных установлено значение utf8. Может быть проблема, даже если это отдельные базы данных?

Спасибо!

РЕДАКТИРОВАТЬ:

Это результат SHOW CREATE TABLE app_messages;

CREATE TABLE `app_messages` (
  `message_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `project_id` bigint(20) NOT NULL,
  `sender_id` bigint(20) NOT NULL,
  `receiver_id` bigint(20) NOT NULL,
  `message` text COLLATE utf8mb4_unicode_ci,
  `timestamp` bigint(20) DEFAULT NULL,
  `is_read` enum('x','') COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`message_id`)
) ENGINE=InnoDB AUTO_INCREMENT=496 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

ИЗМЕНИТЬ 2:

Я выполнил следующую команду:

INSERT INTO app_messages (message_id, project_id, sender_id, receiver_id, message, timestamp, is_read)
VALUES ('496','322','77','188', '😜' ,'1473413606','x');

И два других, похожие на 😂 и 👻

Их без проблем вставили в таблицу:

enter image description here

Но в реальном приложении я действительно вижу: ? (на этот раз только один? А не 4)

22
FrancescoMussi 5 Сен 2016 в 10:58

7 ответов

Лучший ответ

Хорошо, мне наконец удалось заставить его работать! Спасибо всем, кто пытался мне помочь, особенно @Rick James и @Gerard Roche.

< Сильный > SUGGESTION :

Если вам нужно работать с эмодзи, в первую очередь проведите простые тесты на localhost. Создайте новую базу данных и создайте новое приложение для тестирования.

Если вы выполните шаги, которые я написал в вопросе, или если вы будете следовать этому руководству: https: //mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4 он должен работать.

Работая локально над новым базовым приложением, у вас будет больше контроля и больше места для проведения всех необходимых тестов.

РЕШЕНИЕ:

В моем случае проблема заключалась в настройке базы данных в CodeIgniter. Неправильная настройка char_set и сопоставления для глупого упущения: я переопределил настройки базы данных в функции сохранения сообщений, чтобы убедиться, что она работает с мобильной базой данных.

< Сильный > ДО :

function message_save ( $data = FALSE )
{   
    $project_db_config                  = array();
    $project_db_config['hostname']      = 'MY_HOST';
    $project_db_config['username']      = 'MY_USERNAME';
    $project_db_config['password']      = 'MY_PASSWORD';
    $project_db_config['database']      = 'MY_DATABASE';

    $mobile_db                          = $this->load->database( $project_db_config, TRUE );

    // other code to save message       
}

< Сильный > ПОСЛЕ :

function message_save ( $data = FALSE )
{
    $mobile_db_connection = $this->load->database('admin_mobile_mh', TRUE);

    // other code to save message
}

ЗАКЛЮЧЕНИЕ:

Приложение должно правильно установить соединение с базой данных. Если у вас правильно настроена база данных, но вы не установили надлежащее соединение с приложением, это не сработает.

Поэтому, если вы столкнетесь с подобными проблемами, убедитесь, что api правильно настроил char_set как utf8mb4 и db_collat как utf8mb4_unicode_ci.

3
FrancescoMussi 16 Сен 2016 в 11:52

Единственный известный мне способ получить ???? для эмодзи - это не указывать столбец , объявленный utf8mb4. Я понимаю, что вы, по-видимому, определили, что столбец объявлен таким образом, но запустите SHOW CREATE TABLE table_name;, чтобы подтвердить это.

Системное значение по умолчанию, значение по умолчанию для базы данных и значение по умолчанию для таблицы не имеют значения, если столбец перекрывает CHARACTER SET.

Примечание ко всем другим попыткам ответа: COLLATION не имеет значения, только CHARACTER SET имеет значение для этого вопроса .

2
Rick James 10 Сен 2016 в 03:25

Сначала загружается my.cnf, затем conf.d/*.cnf.

Вместо изменения my.cnf * (что может быть переопределено конфигурациями в conf.d/*.cnf) создайте пользовательскую конфигурацию переопределения, например conf.d/90-my.cnf.

Использование префикса 90 гарантирует, что пользовательские настройки загружаются последними, что означает, что они перезаписывают любые ранее установленные настройки.

Чтобы убедиться, что новая конфигурация перезагружена, см. Перезагрузить без перезапуска службы MySQL.

Пример структуры конфигурации (Linux)

.
├── conf.d
│   ├── 90-my.cnf
│   ├── conn.cnf
│   ├── my5.6.cnf
│   └── mysqld_safe_syslog.cnf
├── debian.cnf
├── debian-start
└── my.cnf

conf.d / 90-my.cnf

# https://mathiasbynens.be/notes/mysql-utf8mb4
# http://stackoverflow.com/q/3513773/934739

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]

character-set-client-handshake = FALSE

# The server character set and collation are used as default values if the
# database character set and collation are not specified in CREATE DATABASE
# statements. They have no other purpose.
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
1
Community 13 Апр 2017 в 12:13

Вместо varchar вы можете изменить значение поля таблицы следующим образом: utf8mb4

Убедитесь, что все наборы символов по умолчанию и текстовые поля ваших таблиц преобразованы в utf8mb4 в дополнение к настройке наборов символов клиента и сервера, например ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4; и так далее.

0
Naresh Kumar P 5 Сен 2016 в 08:08

Привет, я использовал EMOJI в android и сохранил его в базе данных orm , используя EMOJI_INDEX . Я сохранил в базе данных в обычном сообщении в строковой форме, но когда я получаю это время, я проверяю, есть ли какие-нибудь эмодзи, а затем конвертирую его в процесс обработки.

textMessage.setText(getItem(pos).file != null ? "":EmojiUtil.getInstance(context).processEmoji(getItem(pos).message, textMessage.getTextSize()));

Посмотрите отсюда, как я изменил Emoji_Index для обработки

if (emojiImages == null || emojiImages.isRecycled()) {
        InputStream localInputStream;
        try {
            localInputStream = context.getAssets().open("emoji/emoji_2x.png");
            Options opts = new Options();
            opts.inPurgeable = true;
            opts.inInputShareable = true;
            emojiImages = BitmapFactory.decodeStream(localInputStream, null, opts);
        } catch (IOException e) {
            return Html.fromHtml(paramString);
        }
    }

Для получения дополнительной информации см. здесь . Спасибо, надеюсь, это поможет вам.

0
Saveen 14 Сен 2016 в 08:39

У меня возникла проблема с серверной версией на Linux. Мне пришлось вручную изменить файл database_interface.lib.php и вокруг этого

if (! PMA_DRIZZLE) {if (! empty ($ GLOBALS ['collation_connection'])) {

Измените его так, чтобы он стал следующим: (обратите внимание на ссылки utf8mb4_unicode_ci )

    // Skip charsets for Drizzle
if (!PMA_DRIZZLE) {
    if (! empty($GLOBALS['collation_connection'])) {
        PMA_DBI_query("SET CHARACTER SET 'utf8mb4';", $link, PMA_DBI_QUERY_STORE);
        $set_collation_con_query = "SET collation_connection = '"
            . PMA_Util::sqlAddSlashes($GLOBALS['collation_connection']) . "';";
        PMA_DBI_query(
            $set_collation_con_query,
            $link,
            PMA_DBI_QUERY_STORE
        );
    } else {
        PMA_DBI_query(
            "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';",
            $link,
            PMA_DBI_QUERY_STORE
        );
    }
}
0
Miguel 12 Июл 2017 в 16:44

Обновленный ответ

Вы можете попробовать кодировку utf8 сопоставление utf8_unicode_ci вместо utf8mb4_unicode_ci.

Запустите этот запрос

ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8 COLLATE utf8_unicode_ci;

старый ответ Вы должны использовать сопоставление utf8mb4_bin вместо utf8mb4_unicode_ci.

Запустите этот запрос

 ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8mb4 COLLATE utf8mb4_bin;

Смайлы будут сохранены в виде кода и снова преобразованы в смайлы в приложениях для Android и iOS. Я тоже использовал этот код в своих проектах.

-2
Gorakh Yadav 9 Сен 2016 в 11:01