2011-12-13 38 views
21

Có vẻ như MySQL does not support ký tự có nhiều hơn 3 byte trong bộ ký tự UTF-8 mặc định của nó. Vì vậy, trong PHP, làm cách nào tôi có thể loại bỏ tất cả 4 ký tự byte (và nhiều hơn) trong một chuỗi và thay thế chúng bằng một số ký tự khác như một số ký tự khác không? Không.Làm thế nào để thay thế/loại bỏ 4 (+) - byte ký tự từ một chuỗi UTF-8 trong PHP?

+1

Bạn có chắc chắn rằng dữ liệu bạn sẽ thao tác sẽ bao giờ chứa các ký tự không phù hợp với utf8 3 byte của mysql? – newtover

+1

Bạn có chắc chắn rằng có cả * các ký tự tương tự không? 3 byte cung cấp cho bạn toàn bộ Máy bay đa ngôn ngữ cơ bản; nếu bạn cần nhiều ký tự hiếm hơn, hãy xem xét mã hóa Unicode khác (ví dụ: utf-16). – Piskvor

+1

Vấn đề là tôi muốn tránh những cái khác, bởi vì MySQL cắt ngắn văn bản tại thời điểm đó nếu ai đó đặt một trong những nhân vật đặc biệt trong đó. – Franz

Trả lời

2

Dưới đây là một ví dụ:

<?php 

mb_internal_encoding("UTF-8"); 

//utf8 string, 13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP 
$str = "qué \xF0\x9D\x92\xB3 tal"; 
$array = mbStringToArray($str); 
print "str: [$str] strlen:" . strlen($str) . " chars:" . count($array) . "\n"; 
$str1 = ""; 
foreach($array as $c) { 
    // print "$c : " . strlen($c) ."\n"; 
    $str1 .= strlen($c)<=3? $c : '?'; 
} 
print "[$str1]\n"; 


function mbStringToArray ($str) { 
    if (empty($str)) return false; 
    $len = mb_strlen($str); 
    $array = array(); 
    for ($i = 0; $i < $len; $i++) { 
     $array[] = mb_substr($str, $i, 1); 
    } 
    return $array; 
} 

Hoặc, một chút nhỏ gọn và hiệu quả hơn:

<?php /// 

mb_internal_encoding("UTF-8"); 

//utf8 string, 13 bytes, 9 utf8 chars, 7 ASCII, 1 in latin1, 1 outside the BMP 
$str = "qué \xF0\x9D\x92\xB3 tal"; 
$str1 = trimOutsideBMP($str); 
print "original: [$str]\n"; 
print "trimmed: [$str1]\n"; 


// Replaces non-BMP characters in the UTF-8 string by a '?' character 
// Assumes UTF-8 default encoding (if not sure, call first mb_internal_encoding("UTF-8");) 
function trimOutsideBMP($str) { 
    if (empty($str)) return $str; 
    $len = mb_strlen($str); 
    $str1 = ''; 
    for ($i = 0; $i < $len; $i++) { 
     $c = mb_substr($str, $i, 1); 
     $str1 .= strlen($c) <= 3 ? $c : '?'; 
    } 
    return $str1; 
} 
+0

Ồ, tôi có nên nói rằng tôi cần một giải pháp không yêu cầu phần mở rộng 'mbstring'? – Franz

+0

Mmm thật tệ. Xem ví dụ ở đây cho cảm hứng: http://noteslog.com/post/full-utf-8-support-in-wordpress/ – leonbloy

1

Came qua câu hỏi này khi cố gắng giải quyết vấn đề của riêng tôi (Facebook spits ra biểu tượng cảm xúc nhất định là 4 các ký tự byte, Amazon Mechanical Turk không chấp nhận các ký tự 4 byte).

tôi đã kết thúc bằng này, không đòi hỏi mở rộng mbstring:

function remove_4_byte($string) { 
    $char_array = preg_split('/(?<!^)(?!$)/u', $string); 
    for($x=0;$x<sizeof($char_array);$x++) { 
     if(strlen($char_array[$x])>3) { 
      $char_array[$x] = ""; 
     } 
    } 
    return implode($char_array, ""); 
} 
+0

Vì một số lý do tôi không thể khiến những người khác làm việc, điều này thực hiện một mẹo. – Mahn

9

Từ 4-byte UTF-8 chuỗi luôn luôn bắt đầu với các byte 0xF0-0xF7, sau đây nên làm việc:

$str = preg_replace('/[\xF0-\xF7].../s', '', $str); 

Hoặc, bạn có thể sử dụng preg_replace ở chế độ UTF-8 nhưng điều này có thể sẽ chậm hơn:

$str = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $str); 

Điều này hoạt động vì các chuỗi UTF-8 4 byte được sử dụng cho các điểm mã trong các máy bay Unicode bổ sung bắt đầu từ 0x10000.

1

Dưới sự thay đổi chức năng 3 và 4 ký tự byte từ utf8 chuỗi '#':

function remove3and4bytesCharFromUtf8Str($str) { 
     return preg_replace('/([\xF0-\xF7]...)|([\xE0-\xEF]..)/s', '#', $str); 
    } 
0

đây là thực hiện của tôi để lọc ra các ký tự 4-byte

0.123.
$string = preg_replace_callback(
    '/./u', 
    function (array $match) { 
     return strlen($match[0]) >= 4 ? null : $match[0]; 
    }, 
    $string 
); 

bạn có thể tinh chỉnh và thay thế null (loại bỏ char) bằng một số chuỗi thay thế. Bạn cũng có thể thay thế >= 4 bằng một số kiểm tra chiều dài byte khác.

Các vấn đề liên quan