UTF8mb4 unicode 破坏 MariaDB JDBC 驱动程序
UTF8mb4 unicode breaking MariaDB JDBC driver
我有一些包含 unicode 字符的产品名称
⚠️PLEASE READ! WORKING KODAK DC215 ZOOM 1.0MP DIGITAL CAMERA - UK
SELLER
heidiSQL 中的查询显示正常
今天早上我从 MySQL 开始设置新的 MariaDB,但是当使用 MariaDB JDBC 通过 ColdFusion 查询检索记录时,我得到
java.lang.StringIndexOutOfBoundsException: begin 0, end 80, length 74
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3410)
at java.base/java.lang.String.substring(String.java:1883)
at org.mariadb.jdbc.internal.com.read.resultset.rowprotocol.TextRowProtocol.getInternalString(TextRowProtocol.java:238)
at org.mariadb.jdbc.internal.com.read.resultset.SelectResultSet.getString(SelectResultSet.java:948)
productname 字段排序规则是 utf8mb4_unicode_520_ci
,我尝试了几个选项。我尝试将其设置为 table 和数据库级别,它允许我这样做。
ColdFusion 管理中的 JDBC 连接字符串是 jdbc:mysql://localhost:3307/usedlens?useUnicode=true&characterEncoding=UTF-8
我注意到从一开始就使用 MariaDB 的现场生产数据库我没有这个问题,但默认字符集是 latin1,并且相同的记录是数据库
????PLEASE READ! WORKING KODAK DC215 ZOOM 1.0MP DIGITAL CAMERA - UK SELLER
这是由于构成表情符号的一系列高位 ASCII 字符造成的。使用第三方工具将 MSSQL 数据导出到 UTF-8 文件以转换为 Excel 时,我遇到了类似的问题。在这种情况下,数据库和文件是正确的,但是第 3 方工具在遇到 emoji 字符时会崩溃。
我们的方法是将表情符号转换为它们的别名,这样信息就不会在这个过程中丢失。 (如果你去掉高 ASCII 字符,你可能会丢失一些上下文。)为了清理表情符号以使用别名,我写了这个 ColdFusion cf-emoji-java (CFC) to leverage emoji-java(JAR 文件)来将表情符号转换为它们的 ASCII7 安全别名。
emojijava = new emojijava();
emojijava.parseToAliases('I like '); // I like :pizza:
从...
- 我不是真的支持表情符号
- 我的数据只是在可预见的未来针对英国、欧洲和美国的产品名称
- 我不想在生产中遇到同样的麻烦(已经默认为 latin1_swedish_ci)
我决定..
匹配生产,所以我在
的帮助下将数据库 table 和字段设置为 latin1_swedish_ci
How to change the CHARACTER SET (and COLLATION) throughout a database?
并去除产品名称中的非 ASCII 字符
==编辑不要这样做,它会去掉太多有用的字符==
<cfset productname = reReplace(productname, "[^\x20-\x7E]", "", "ALL")>
以下是我们如何去除高位 ASCII 字符同时保留任何可能被挽救的字符:
string function ASCIINormalize(string inputString=""){
return createObject( 'java', 'java.text.Normalizer' ).normalize( javacast("string", arguments.inputString) , createObject( 'java', 'java.text.Normalizer$Form' ).valueOf('NFD') ).replaceAll('\p{InCombiningDiacriticalMarks}+','').replaceAll('[^\p{ASCII}]+','');
}
productname = ASCIINormalize(productname);
/*
Comparisons using java UDF versus reReplace regex:
"ABC Café ’test" (note: High ASCII non-normal whitespace characters used.)
ASCIINormalize = "ABC Cafe test"
reReplace = "ABC Caf test"
"čeština"
ASCIINormalize = "cestina"
reReplace = "etina"
"Häuser Bäume Höfe Gärten"
ASCIINormalize = "Hauser Baume Hofe Garten"
reReplace = "Huser Bume Hfe Grten"
*/
我有一些包含 unicode 字符的产品名称
⚠️PLEASE READ! WORKING KODAK DC215 ZOOM 1.0MP DIGITAL CAMERA - UK SELLER
heidiSQL 中的查询显示正常
今天早上我从 MySQL 开始设置新的 MariaDB,但是当使用 MariaDB JDBC 通过 ColdFusion 查询检索记录时,我得到
java.lang.StringIndexOutOfBoundsException: begin 0, end 80, length 74
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3410)
at java.base/java.lang.String.substring(String.java:1883)
at org.mariadb.jdbc.internal.com.read.resultset.rowprotocol.TextRowProtocol.getInternalString(TextRowProtocol.java:238)
at org.mariadb.jdbc.internal.com.read.resultset.SelectResultSet.getString(SelectResultSet.java:948)
productname 字段排序规则是 utf8mb4_unicode_520_ci
,我尝试了几个选项。我尝试将其设置为 table 和数据库级别,它允许我这样做。
ColdFusion 管理中的 JDBC 连接字符串是 jdbc:mysql://localhost:3307/usedlens?useUnicode=true&characterEncoding=UTF-8
我注意到从一开始就使用 MariaDB 的现场生产数据库我没有这个问题,但默认字符集是 latin1,并且相同的记录是数据库
????PLEASE READ! WORKING KODAK DC215 ZOOM 1.0MP DIGITAL CAMERA - UK SELLER
这是由于构成表情符号的一系列高位 ASCII 字符造成的。使用第三方工具将 MSSQL 数据导出到 UTF-8 文件以转换为 Excel 时,我遇到了类似的问题。在这种情况下,数据库和文件是正确的,但是第 3 方工具在遇到 emoji 字符时会崩溃。
我们的方法是将表情符号转换为它们的别名,这样信息就不会在这个过程中丢失。 (如果你去掉高 ASCII 字符,你可能会丢失一些上下文。)为了清理表情符号以使用别名,我写了这个 ColdFusion cf-emoji-java (CFC) to leverage emoji-java(JAR 文件)来将表情符号转换为它们的 ASCII7 安全别名。
emojijava = new emojijava();
emojijava.parseToAliases('I like '); // I like :pizza:
从...
- 我不是真的支持表情符号
- 我的数据只是在可预见的未来针对英国、欧洲和美国的产品名称
- 我不想在生产中遇到同样的麻烦(已经默认为 latin1_swedish_ci)
我决定..
匹配生产,所以我在
的帮助下将数据库 table 和字段设置为 latin1_swedish_ciHow to change the CHARACTER SET (and COLLATION) throughout a database?
并去除产品名称中的非 ASCII 字符
==编辑不要这样做,它会去掉太多有用的字符==
<cfset productname = reReplace(productname, "[^\x20-\x7E]", "", "ALL")>
以下是我们如何去除高位 ASCII 字符同时保留任何可能被挽救的字符:
string function ASCIINormalize(string inputString=""){
return createObject( 'java', 'java.text.Normalizer' ).normalize( javacast("string", arguments.inputString) , createObject( 'java', 'java.text.Normalizer$Form' ).valueOf('NFD') ).replaceAll('\p{InCombiningDiacriticalMarks}+','').replaceAll('[^\p{ASCII}]+','');
}
productname = ASCIINormalize(productname);
/*
Comparisons using java UDF versus reReplace regex:
"ABC Café ’test" (note: High ASCII non-normal whitespace characters used.)
ASCIINormalize = "ABC Cafe test"
reReplace = "ABC Caf test"
"čeština"
ASCIINormalize = "cestina"
reReplace = "etina"
"Häuser Bäume Höfe Gärten"
ASCIINormalize = "Hauser Baume Hofe Garten"
reReplace = "Huser Bume Hfe Grten"
*/