2013-02-20 4 views
7

W mojej bazy danych pojawia się błądSprawdzanie typu UTF-8 bajtów danych 3-lub 4-bajtowy Unicode

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

używam Java i MySQL 5. Znam 4-bajtowy Unicode jest legalny i Java , ale nielegalne w MySQL 5, myślę, że to może spowodować mój problem i chcę sprawdzić typ moich danych, więc oto moje pytanie: Jak mogę sprawdzić, czy moje dane UTF-8 są 3-bajtowe lub 4-bajtowe Unicode ?

+0

Proponuję patrząc na typ danych kolumna limit długości i rozmiar danych, które próbują wstawić pierwszy. Jeśli wstawiasz 100K znaków do "VARCHAR", nie ma żadnego kodowania. – Jon

+0

Nie sądzę, że 4-bajtowe kodowane znaki UTF-8 są przyczyną tego problemu. Bardziej prawdopodobną przyczyną jest ciąg znaków * n *, który pobiera * m * bajtów (z * m *> * n *), gdy kodowanie UTF-8, ale powinien być umieszczony w VARCHAR (* n *). –

+0

@Jon Sprawdziłem to pierwszy, i to nie był problem, rozwiązałem go już, ale nadal myślę, że użyję sprawdzania kodowania w przyszłości, thaks o pomoc – akuzma

Odpowiedz

15

koduje wszystko w podstawowej płaszczyźnie wielojęzycznej (tj. U + 0000 do U + FFFF włącznie) w 1-3 bajtach. W związku z tym wystarczy sprawdzić, czy wszystko w łańcuchu znaków jest w BMP wartością.

W Javie, czyli sprawdzenie, czy każdy char (który jest UTF-16 jednostka kod) jest wysoki lub niski charakter zastępczym, jak Java użyje zastępczych pary do kodowania znaków, BMP non:

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

Jeśli nie chcą wspierać poza BMP, można po prostu rozebrać te znaki przed przekazaniem go do MySQL:

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

Jeśli chcesz wesprzeć poza BMP, trzeba MySQL 5.5+ i trzeba zmienić wszystko, co utf8 do utf8mb4 (sortowanie, zestawy znaków ...). Ale potrzebujesz również wsparcia w sterowniku, którego nie znam. Obsługa tych znaków w Javie jest również uciążliwa, ponieważ są one rozłożone na 2 chars i dlatego wymagają specjalnej obsługi w wielu operacjach.

+0

To faktycznie nie działa dobrze, ponieważ regexps są oceniane na poziomie codepoints, a nie codeunits. Musisz dopasować znaki poza zakresem \ u0000- \ uFFFF (zobacz moją odpowiedź). – verglor

+0

@ jako512 Jest to zaskakujące, ponieważ wszystko inne zajmuje się jednostkami kodu: ja zredagowałem je do pracy z pełnymi znakami nieBMP, ale zamiarem pierwotnej wersji było usunięcie niepowiązanych surogatów również – Esailija

+0

Pamiętaj, że REGEX może być nieco zmodyfikowany dla Twojego języka . Dla PHP użyj 'preg_replace ('/ [^ \ x {0000} - \ x {FFFF}]/u', '\ x {FFFD}', $ input);' – DOOManiac

3

najlepszym podejściem do paska non-BMP charactres w Javie, że found jest następujący:

inputString.replaceAll("[^\\u0000-\\uFFFF]", "\uFFFD");