2013-02-20 42 views
7

Trong cơ sở dữ liệu của tôi, tôi nhận được lỗiKiểm tra kiểu UTF-8 dữ liệu 3-byte, hoặc 4-byte Unicode

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 

tôi sử dụng Java và MySQL 5. Như tôi biết 4-byte Unicode là i pháp Java , nhưng bất hợp pháp trong MySQL 5, tôi nghĩ rằng nó có thể gây ra vấn đề của tôi và tôi muốn kiểm tra loại dữ liệu của tôi, vì vậy đây là câu hỏi của tôi: Làm thế nào tôi có thể kiểm tra dữ liệu UTF-8 của tôi là Unicode 3 byte hoặc 4 byte ?

+0

Tôi đề nghị xem xét giới hạn độ dài kiểu dữ liệu cột của bạn và kích thước của dữ liệu bạn đang cố gắng để chèn đầu tiên. Nếu bạn đang chèn 100K ký tự vào một 'VARCHAR' không có mã hóa là có lỗi. – Jon

+0

Tôi không nghĩ rằng các ký tự mã hóa UTF-8 4 byte là lý do cho vấn đề này. Nguyên nhân có nhiều khả năng là chuỗi * n * -character nhận * m * byte (với * m *> * n *) khi mã hóa UTF-8, nhưng nên được đưa vào VARCHAR (* n *). –

+0

@Jon Tôi đã kiểm tra nó trước, và đó không phải là vấn đề tôi đã giải quyết nó, nhưng tôi vẫn nghĩ rằng tôi sẽ sử dụng kiểm tra mã hóa trong tương lai, thaks để được giúp đỡ tất cả – akuzma

Trả lời

15

UTF-8 mã hóa mọi thứ trên mặt phẳng đa ngôn ngữ cơ bản (ví dụ: U + 0000 thành U + FFFF) trong 1-3 byte. Do đó, bạn chỉ cần kiểm tra xem mọi thứ trong chuỗi trong BMP.

Trong Java, có nghĩa là kiểm tra xem có bất kỳ char (mà là một mã đơn vị UTF-16) là một nhân vật đại diện cao hay thấp, như Java sẽ sử dụng cặp thay thế để mã hóa ký tự-BMP phi:

public static boolean isEntirelyInBasicMultilingualPlane(String text) { 
    for (int i = 0; i < text.length(); i++) { 
     if (Character.isSurrogate(text.charAt(i))) { 
      return false; 
     } 
    } 
    return true; 
} 
10

Nếu bạn không muốn hỗ trợ vượt BMP, bạn chỉ có thể tách những nhân vật trước khi đưa nó cho MySQL:

public static String withNonBmpStripped(String input) { 
    if(input == null) throw new IllegalArgumentException("input"); 
    return input.replaceAll("[^\\u0000-\\uFFFF]", ""); 
} 

Nếu bạn muốn hỗ trợ vượt BMP, bạn cần MySQL 5.5+ và bạn cần phải thay đổi tất cả mọi thứ đó là utf8 đến utf8mb4 (collations, charsets ...). Nhưng bạn cũng cần sự hỗ trợ cho điều này trong tài xế mà tôi là không quen thuộc. Xử lý các ký tự này trong Java cũng là một nỗi đau vì chúng được trải rộng trên 2 chars và do đó cần xử lý đặc biệt trong nhiều thao tác.

+0

Điều này thực sự không hoạt động tốt vì regexps được đánh giá ở cấp độ các điểm mã, không phải là các mã lệnh. Bạn cần khớp các ký tự bên ngoài phạm vi \ u0000- \ uFFFF (xem câu trả lời của tôi). – verglor

+0

@ jako512 Điều đó thật đáng ngạc nhiên vì mọi thứ khác đề cập đến các đơn vị mã: II đã chỉnh sửa nó để hoạt động với các ký tự không phải là fullBMP nhưng ý định đằng sau phiên bản gốc là loại bỏ các thay thế chưa được ghép nối cũng – Esailija

+0

Lưu ý rằng REGEX có thể được điều chỉnh một chút cho ngôn ngữ của bạn . Đối với PHP, sử dụng 'preg_replace ('/ [^ \ x {0000} - \ x {FFFF}]/u', '\ x {FFFD}', $ đầu vào);' – DOOManiac

3

cách tiếp cận tốt nhất để dải charactres phi BMP trong java mà tôi found như sau:

inputString.replaceAll("[^\\u0000-\\uFFFF]", "\uFFFD"); 
Các vấn đề liên quan