No se puede almacenar emoji en la base de datos
LA SITUACIÓN :
Lo siento de antemano si esta pregunta ya se ha hecho, pero las soluciones no funcionan para mí.
- ¿Cómo utilizar BLOB con JSON y PHP?
- ¿Cómo integrar prestashop con android?
- MySQL - Combinando INSERT, VALUES y SELECT?
- Usar cuenta de servicio para verificar Google InAppPurchase
- Cómo subir imágenes al servidor Php y almacenar en phpmyadmin
No importa lo que intente, no puedo almacenar emoji en mi base de datos. Se guardan como ????
.
Los únicos emojis que se guardan correctamente son los que requieren sólo 3 bytes, como la cara tímida o el sol.
El utf8mb4 real no está funcionando.
Se ha probado tanto en Android como en Ios. Con los mismos resultados.
VERSIONES :
Mysql: 5.5.49
CodeIgniter: 3.0.0
LOS PASOS :
-
He modificado el conjunto de caracteres de base de datos y propiedades de intercalación.
ALTER DATABASE my_database CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci
-
He modificado el conjunto de caracteres de tabla y las propiedades de intercalación.
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
-
He establecido cada campo de la tabla, cuando sea posible, como Codificación:
UTF-8(ut8mb4)
y Colación:utf8mb4_unicode_ci
-
He modificado la conexión de la base de datos en la aplicación CodeIgniter.
-
He ejecutado el siguiente:
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
-
Por último también he intentado esto:
REPAIR TABLE table_name; OPTIMIZE TABLE table_name;
REPAIR TABLE table_name; OPTIMIZE TABLE table_name;
Todo debería haber sido configurado correctamente, pero aún así no funciona.
AJUSTES DE BASE DE DATOS :
Este es el resultado ejecutando el siguiente comando:
`SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';`
AJUSTES DE LA MESA :
Un screeshot de la estructura de la mesa:
CONEXIÓN DE BASE DE DATOS :
Estas son las configuraciones de conexión a la base de datos dentro de database.php (note que esta no es la única base de datos, también hay otras que se conectan usando 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 );
CONFIGURACIONES MY.CNF :
Este es el contenido completo del archivo 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
LA PREGUNTA :
¿Sabes por qué no funciona? ¿Me estoy perdiendo de algo?
HIPOTESIS 1 :
No estoy seguro, pero la causa del problema puede ser esta:
Como se puede ver en my.cnf character-set-server
se establece claramente como utf8mb4
:
Pero después de ejecutar la consulta en la base de datos:
SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
El resultado es que character-set-server = latin1
¿Sabes por qué es eso? ¿Por qué no se está actualizando?
HIPOTESIS 2 :
La aplicación utiliza varias bases de datos diferentes. Este se establece en utf8mb4, pero todos los demás se establecen en utf8. Puede ser un problema incluso si son bases de datos separadas?
¡Gracias!
EDITAR:
Este es el resultado de 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
EDIT 2:
He ejecutado el siguiente comando:
INSERT INTO app_messages (message_id, project_id, sender_id, receiver_id, message, timestamp, is_read) VALUES ('496','322','77','188', '😜' ,'1473413606','x');
Y otros dos similares con 😂 y 👻
Se insertaban en la mesa sin problemas:
Pero en la aplicación real lo que realmente veo es ?
(esta vez sólo uno? y no 4)
- Cargar archivo de imágenes múltiples mediante HttpURLConnection
- Ejecutar Gps como servicio de fondo y enviar coordenadas al servidor web (PHP)
- SHA1 en Java y PHP con resultados diferentes
- Almacenar una imagen codificada en base64 desde android vía php en mysql
- Valor nulo devuelto de la conexión entre android y base de datos MYSQL
- El navegador de Android no funciona con la geolocalización
- Android JSON a PHP Server y volver
- No recibe la notificación de push de GCM de Amazon SNS
La única manera que sé de conseguir ????
para un Emoji es no tener la columna declarada utf8mb4
. Entiendo que aparentemente ha determinado que la columna está declarada de esa manera, pero por favor ejecute SHOW CREATE TABLE table_name;
para confirmarlo.
El valor predeterminado del sistema, el valor predeterminado de la base de datos y el valor por omisión de la tabla son irrelevantes si la columna reemplaza al conjunto de CHARACTER SET
.
Una nota a todos los otros intentos de respuestas: El COLLATION
es irrelevante, sólo el CHARACTER SET
es relevante para esta pregunta .
my.cnf
se carga primero, luego conf.d/*.cnf
.
En lugar de modificar my.cnf
* (que puede ser sobrescrita por configuraciones en conf.d/*.cnf
), cree una configuración de sustitución personalizada, por ejemplo, conf.d/90-my.cnf
.
El prefijo 90
garantiza que los ajustes personalizados se carguen por último, lo que significa que sobreescriben cualquier configuración anterior.
Para asegurarse de que se vuelve a cargar la nueva configuración, consulte Recargar sin reiniciar el servicio MySQL .
Ejemplo de estructura de configuración (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
Bueno, finalmente me las arreglé para hacerlo funcionar! Gracias a todos los que intentaron ayudarme, especialmente @Rick James y @Gerard Roche.
SUGERENCIA:
Si necesita trabajar con emoji en primer lugar hacer pruebas simples en localhost. Cree una nueva base de datos y haga una nueva aplicación para fines de prueba.
Si sigues los pasos que escribí en la pregunta o si sigues este tutorial: https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4 debe funcionar.
Trabajando localmente en una nueva aplicación básica tendrás más control y más espacio para hacer todas las pruebas que necesites.
SOLUCIÓN:
En mi caso el problema estaba en la configuración de la base de datos en CodeIgniter. No estaba configurando adecuadamente el char_set y la colación para una estúpida visión: Estaba anulando la configuración de la base de datos en la función que guardaba mensajes para estar seguro de que estaba trabajando con la base de datos móvil.
ANTES DE:
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 }
DESPUÉS:
function message_save ( $data = FALSE ) { $mobile_db_connection = $this->load->database('admin_mobile_mh', TRUE); // other code to save message }
CONCLUSIÓN:
La aplicación debe establecer la conexión a la base de datos correctamente. Si tiene la base de datos correctamente configurada pero no establece la conexión correcta con su aplicación, no funcionará.
Así que si usted encuentra problemas similares asegúrese de que la api correctamente configurar el char_set
como utf8mb4
y db_collat
como utf8mb4_unicode_ci
.
En lugar de varchar, puede cambiar el valor de la tabla archivada como se indica a utf8mb4
Asegúrese de que todos los conjuntos de caracteres y campos de texto por defecto de sus tablas se conviertan en utf8mb4, además de establecer los conjuntos de caracteres de cliente y servidor, por ejemplo ALTER TABLE mytable charset=utf8mb4, MODIFY COLUMN textfield1 VARCHAR(255) CHARACTER SET utf8mb4,MODIFY COLUMN textfield2 VARCHAR(255) CHARACTER SET utf8mb4;
y así.
hola he utilizado EMOJI en android y lo almacené en la base de datos orm utilizando EMOJI_INDEX . He guardado en db en el mensaje normal en forma de cadena, pero cuando me sale ese tiempo comprobar si hay cualquier emoji luego convertirlo en procesemoji.
textMessage.setText(getItem(pos).file != null ? "":EmojiUtil.getInstance(context).processEmoji(getItem(pos).message, textMessage.getTextSize()));
Echa un vistazo desde aquí cómo cambié Emoji_Index a proceso
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); } }
Para más información echa un vistazo desde aquí . Gracias, espero que esto te ayude.
Tuve un problema con la versión del servidor, en linux. Tuve que cambiar el archivo database_interface.lib.php manualmente y alrededor de este
if (! PMA_DRIZZLE) {if (! empty ($ GLOBALS ['collation_connection'])) {
cambiarlo de modo que, se convierta en esto: (anote las referencias 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 ); } }
Respuesta actualizada
Puede intentar charset utf8
collation utf8_unicode_ci
lugar de utf8mb4_unicode_ci
.
ejecutar esta consulta
ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8 COLLATE utf8_unicode_ci;
old answer Debe utilizar collation utf8mb4_bin
lugar de utf8mb4_unicode_ci
.
ejecutar esta consulta
ALTER TABLE table_name CHANGE `column_name` `column_name` TEXT CHARSET utf8mb4 COLLATE utf8mb4_bin;
Emojis se almacenará como código y se convertirá en emojis de nuevo en Android y aplicaciones de iOS. He utilizado este código en mis proyectos también.
- Cómo establecer el color del título en ActionBarSherlock?
- Cómo simular la entrada de audio a micrófono utilizando el archivo .wav