数据库字符集 UTF16 未显示正确的字符
Database charset UTF16 not showing proper character
我通过将每个 table 的数据库排序规则和字符集设置为 utf16
在 mysql 中创建了一个数据库
我选择 utf16 的原因是,我想存储各种数学方程式,例如 ΦB =B.A=BAcosθ β (实际上在 ΦB 中,B 是上标)
不仅上面的公式而且数据库可能有任何种类的希腊字母,如图所示link
我试图通过读取 Microsoft excel 文件来插入数据
在执行查询之前,java 代码中的一切似乎都是正确的,但是在插入数据库之后,它显示为 ?B =B.A=BAcos? ?
根据 utf16 支持的字符集 Link 上面的等式对我来说应该没问题
但事实并非如此。
有什么想法吗?
数据库Table架构
mysql> SHOW CREATE TABLE formulae;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| formulae | CREATE TABLE `formulae` (
`formulaeid` int(11) NOT NULL AUTO_INCREMENT,
`formulae` text CHARACTER SET utf16,
`concept_conceptid` int(11) NOT NULL,
PRIMARY KEY (`formulaeid`),
KEY `fk_formulae_concept_idx` (`concept_conceptid`),
CONSTRAINT `fk_formulae_concept` FOREIGN KEY (`concept_conceptid`) REFERENCES `concept` (`conceptid`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
代码:
final static int CONCEPT_SHEET_NUMBER = 0;
final static int FORMULAE_SHEET_NUMBER = 1;
//Reads xl file
public void readProductArgExcel(File inputFile) throws IOException {
FileInputStream file = new FileInputStream(inputFile);
XSSFWorkbook workBook = new XSSFWorkbook(file);
boolean isError = false;
for (int sheetNumber = 0; sheetNumber < workBook.getNumberOfSheets(); sheetNumber++) {
XSSFSheet sheet = workBook.getSheetAt(sheetNumber);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
isError = false;
Row row = sheet.getRow(i);
List<Object> columnValues = new ArrayList<Object>();
for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
Cell cell = row.getCell(j);
if (!(cell == null)) {
if (cell.getCellType() == 0) {
Integer conceptId = (int) cell
.getNumericCellValue();
columnValues.add(conceptId);
}
if (cell.getCellType() == 1) {
String rowString = cell
.getStringCellValue();
columnValues.add(rowString);
}
switch (sheetNumber) {
case CONCEPT_SHEET_NUMBER:
break;
//XL file has two sheets, second sheet has few formulae
case FORMULAE_SHEET_NUMBER:{
if(j == 1){
if(columnValues.size() >= 2)
//this xl sheet has column 1 - formula, column2 - integer
insertFormulae((String)columnValues.get(0),(Integer)columnValues.get(1));
}
break;
}
default:
break;
}
}
}
}
System.out.println(sheet.getSheetName());
}
}
public static Connection getConnection() throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {
Connection connection = null;
/*Tried with but didn't work
jdbc:mysql://localhost:3306/formulaeDB?useUnicode=true&characterEncoding=utf16
but it perfectly works with
jdbc:mysql://localhost:3306/formulaeDB?useUnicode=true&characterEncoding=utf8
*/
String connectionURL = "jdbc:mysql://localhost:3306/formulaeDB";
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root","root");
/*The below code throws an exception
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Variable 'character_set_client' can't be set to the value of 'utf16'
*/
String queryString = "SET NAMES utf16";
PreparedStatement preparedStatement = connection.prepareStatement(
queryString, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.executeUpdate();
return connection;
}
//To insert into table
public static void insertFormulae(String formula,Integer conceptId){
String queryString = "INSERT INTO formulae(formulae,concept_conceptid) VALUES(?,?)";
Connection connection;
try {
connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
queryString, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, formula);
preparedStatement.setInt(2, conceptId);
preparedStatement.executeUpdate();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String st[]) throws IOException {
ExcelParser r = new ExcelParser();
r.readProductArgExcel(new File(
“c://data/Formulae.xlsx"));
}
您需要确保您从 excel 读取的数据是正确的,您的 table 已正确创建,您的连接已正确设置,并且您的代码读取excel 中的数据并将它们写入数据库工作正常。
如果这一切似乎都没有问题,那么接下来要怀疑的是,也许数据库中的数据没有问题,而你观察数据的方式是错误的。
具体来说,如果您使用 mysql 控制台命令,则需要确保控制台能够正确显示从数据库中获取的 unicode 字段。
图形数据库管理工具通常没有这些缺点,那么为什么不使用与 MySQL 一起提供的 "MySQL Workbench" 工具呢?
这应该可以解决您的 unicode 问题。
您还会遇到另一个问题:格式化。
上标和下标是 unicode 几乎不支持的东西,(你可以有几个上标数字,仅此而已,)所以 excel 在单元格文本中使用特殊格式来表示上标和下标。
不幸的是,当您按照自己的方式阅读单元格时,excel 不会为您提供这种格式。这似乎是一个很难解决的问题,但这里似乎有某种解决方案:Reading rich text from an Excel cell
我没听说过任何暴露utf16的产品。 Utf8 是常用的交换格式。 MySQL 的 utf8mb4 甚至更好,因为它允许 4 字节的 utf8 字符(它的 utf8 不允许)。
将所有设置更改为 utf8 以查看它们是否可以更好地互操作。
如果您已经有包含 utf16 字符的数据文件或数据库,那么问题就更复杂了。
我通过将每个 table 的数据库排序规则和字符集设置为 utf16
在 mysql 中创建了一个数据库我选择 utf16 的原因是,我想存储各种数学方程式,例如 ΦB =B.A=BAcosθ β (实际上在 ΦB 中,B 是上标)
不仅上面的公式而且数据库可能有任何种类的希腊字母,如图所示link
我试图通过读取 Microsoft excel 文件来插入数据 在执行查询之前,java 代码中的一切似乎都是正确的,但是在插入数据库之后,它显示为 ?B =B.A=BAcos? ?
根据 utf16 支持的字符集 Link 上面的等式对我来说应该没问题 但事实并非如此。
有什么想法吗?
数据库Table架构
mysql> SHOW CREATE TABLE formulae;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| formulae | CREATE TABLE `formulae` (
`formulaeid` int(11) NOT NULL AUTO_INCREMENT,
`formulae` text CHARACTER SET utf16,
`concept_conceptid` int(11) NOT NULL,
PRIMARY KEY (`formulaeid`),
KEY `fk_formulae_concept_idx` (`concept_conceptid`),
CONSTRAINT `fk_formulae_concept` FOREIGN KEY (`concept_conceptid`) REFERENCES `concept` (`conceptid`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf16 COLLATE=utf16_unicode_ci |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
代码:
final static int CONCEPT_SHEET_NUMBER = 0;
final static int FORMULAE_SHEET_NUMBER = 1;
//Reads xl file
public void readProductArgExcel(File inputFile) throws IOException {
FileInputStream file = new FileInputStream(inputFile);
XSSFWorkbook workBook = new XSSFWorkbook(file);
boolean isError = false;
for (int sheetNumber = 0; sheetNumber < workBook.getNumberOfSheets(); sheetNumber++) {
XSSFSheet sheet = workBook.getSheetAt(sheetNumber);
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
isError = false;
Row row = sheet.getRow(i);
List<Object> columnValues = new ArrayList<Object>();
for (int j = 0; j < row.getPhysicalNumberOfCells(); j++) {
Cell cell = row.getCell(j);
if (!(cell == null)) {
if (cell.getCellType() == 0) {
Integer conceptId = (int) cell
.getNumericCellValue();
columnValues.add(conceptId);
}
if (cell.getCellType() == 1) {
String rowString = cell
.getStringCellValue();
columnValues.add(rowString);
}
switch (sheetNumber) {
case CONCEPT_SHEET_NUMBER:
break;
//XL file has two sheets, second sheet has few formulae
case FORMULAE_SHEET_NUMBER:{
if(j == 1){
if(columnValues.size() >= 2)
//this xl sheet has column 1 - formula, column2 - integer
insertFormulae((String)columnValues.get(0),(Integer)columnValues.get(1));
}
break;
}
default:
break;
}
}
}
}
System.out.println(sheet.getSheetName());
}
}
public static Connection getConnection() throws InstantiationException,
IllegalAccessException, ClassNotFoundException, SQLException {
Connection connection = null;
/*Tried with but didn't work
jdbc:mysql://localhost:3306/formulaeDB?useUnicode=true&characterEncoding=utf16
but it perfectly works with
jdbc:mysql://localhost:3306/formulaeDB?useUnicode=true&characterEncoding=utf8
*/
String connectionURL = "jdbc:mysql://localhost:3306/formulaeDB";
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(connectionURL, "root","root");
/*The below code throws an exception
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Variable 'character_set_client' can't be set to the value of 'utf16'
*/
String queryString = "SET NAMES utf16";
PreparedStatement preparedStatement = connection.prepareStatement(
queryString, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.executeUpdate();
return connection;
}
//To insert into table
public static void insertFormulae(String formula,Integer conceptId){
String queryString = "INSERT INTO formulae(formulae,concept_conceptid) VALUES(?,?)";
Connection connection;
try {
connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
queryString, PreparedStatement.RETURN_GENERATED_KEYS);
preparedStatement.setString(1, formula);
preparedStatement.setInt(2, conceptId);
preparedStatement.executeUpdate();
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String st[]) throws IOException {
ExcelParser r = new ExcelParser();
r.readProductArgExcel(new File(
“c://data/Formulae.xlsx"));
}
您需要确保您从 excel 读取的数据是正确的,您的 table 已正确创建,您的连接已正确设置,并且您的代码读取excel 中的数据并将它们写入数据库工作正常。
如果这一切似乎都没有问题,那么接下来要怀疑的是,也许数据库中的数据没有问题,而你观察数据的方式是错误的。
具体来说,如果您使用 mysql 控制台命令,则需要确保控制台能够正确显示从数据库中获取的 unicode 字段。
图形数据库管理工具通常没有这些缺点,那么为什么不使用与 MySQL 一起提供的 "MySQL Workbench" 工具呢?
这应该可以解决您的 unicode 问题。
您还会遇到另一个问题:格式化。
上标和下标是 unicode 几乎不支持的东西,(你可以有几个上标数字,仅此而已,)所以 excel 在单元格文本中使用特殊格式来表示上标和下标。
不幸的是,当您按照自己的方式阅读单元格时,excel 不会为您提供这种格式。这似乎是一个很难解决的问题,但这里似乎有某种解决方案:Reading rich text from an Excel cell
我没听说过任何暴露utf16的产品。 Utf8 是常用的交换格式。 MySQL 的 utf8mb4 甚至更好,因为它允许 4 字节的 utf8 字符(它的 utf8 不允许)。
将所有设置更改为 utf8 以查看它们是否可以更好地互操作。
如果您已经有包含 utf16 字符的数据文件或数据库,那么问题就更复杂了。