【问题标题】:Database charset UTF16 not showing proper character数据库字符集 UTF16 未显示正确的字符
【发布时间】:2015-02-13 08:50:04
【问题描述】:

我通过将数据库的排序规则和每个表的字符集设置为 utf16 在 mysql 中创建了一个数据库

我选择 utf16 的原因是,我想存储各种数学方程,例如 ΦB =B.A=BAcosθ β(实际上在 ΦB 中,B 是上标)

不仅上面的公式,而且数据库可能有任何类型的希腊字母,如图所示link

我尝试通过读取 microsoft excel 文件来插入数据 在执行查询之前,Java 代码中的一切似乎都是正确的,但在插入数据库之后,它显示为 ?B =B.A=BAcos? ?

根据 utf16 支持的字符集 Link,上面的等式对我来说应该不错 但事实并非如此。

有什么想法吗?

数据库表架构

    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"));
        }

【问题讨论】:

  • 在插入之前执行以下语句 SET NAMES UTF-16 并且您的数据应该被正确存储
  • 在给朋友发短信时使用“hv”,而不是在 stackoverflow 上提问时。
  • @MikeNakis 请帮我解决问题。谢谢
  • 您是否害怕如果您向我们展示您的代码我们可能会窃取它?显示将数据从 excel 复制到数据库的代码,并准确告诉我们您是如何发现数据库中的数据已损坏的。
  • @MikeNakis 我已经用代码更新了帖子,数据库和所有表都在 utf16 排序规则和字符集中

标签: java mysql character-encoding


【解决方案1】:

您需要确保您从 excel 中读取的数据是正确的,您的表已正确创建,您的连接已正确设置,并且您从 excel 中读取数据并将其写入数据库的代码是正常工作。

如果这一切似乎都没有问题,那么接下来要怀疑的是,也许数据库中的数据还不错,而你观察数据的方式是错误的。

具体来说,如果您使用 mysql 控制台命令,那么您需要确保控制台能够正确显示从您的数据库中获取的 unicode 字段。

图形数据库管理工具通常没有这些缺点,那么为什么不使用 MySQL 附带的“MySQL Workbench”工具呢?

这应该可以解决您的 unicode 问题。

你还会遇到另一个问题:格式化。

上标和下标是 unicode 很少支持的东西,(你可以有几个上标数字,仅此而已),因此 excel 在单元格文本中使用特殊格式来表示上标和下标。

不幸的是,当您以您的方式阅读单元格时,excel 不会为您提供这种格式。这似乎是一个很难解决的问题,但这里似乎有某种解决方案:Reading rich text from an Excel cell

【讨论】:

  • 我也用过Mysql工作台,还有sequel pro tool,下标和上标同样的问题
【解决方案2】:

我听说没有公开 utf16 的产品。 Utf8 是交换的常用格式。 MySQL 的 utf8mb4 更好,因为它允许 4 字节的 utf8 字符(而它的 utf8 不允许)。

将所有设置更改为 utf8 以查看它们是否更好地互操作。

如果您已经有包含 utf16 字符的数据文件或数据库,那么问题就更大了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-28
    • 2013-05-15
    • 1970-01-01
    相关资源
    最近更新 更多