2013-02-24 43 views
5

Tôi gặp sự cố với UTF-8 và mb_strtoupper.PHP: mb_strtoupper không hoạt động

mb_internal_encoding('UTF-8'); 
$guesstitlestring='Le Courrier de Sáint-Hyácinthe'; 

$encoding=mb_detect_encoding($guesstitlestring); 
if ($encoding!=='UTF-8') $guesstitlestring=mb_convert_encoding($guesstitlestring,'UTF-8',$encoding); 

echo "DEBUG1 $guesstitlestring\n"; 
$guesstitlestring=mb_strtoupper($guesstitlestring); 
echo "DEBUG2 $guesstitlestring\n"; 

Kết quả:

DEBUG1 Le Courrier de Sáint-Hyácinthe 
DEBUG2 LE COURRIER DE S?INT-HY?CINTHE 

Tôi không hiểu tại sao điều này đang xảy ra? Tôi đang cố gắng cẩn thận như tôi có thể với mã hóa. Chuỗi được đưa ra đầu tiên dưới dạng UTF-8, được xác minh và có thể được chuyển thành UTF-8. Nó là một cơn ác mộng!

CẬP NHẬT

Vì vậy, tôi đã tìm ra rằng đây là do sự kết hợp của bước vào tôi những lập luận thông qua giao diện điều khiển và các đối số quay trở lại ra khỏi console. Vì vậy, họ đã bị cắt xén cả trên đường vào và đường ra. Giải pháp là không nhập bất kỳ đối số nào theo cách này, hoặc lấy các đối số ra theo cách này.

Cảm ơn mọi người đã giúp bạn giải quyết vấn đề này!

+0

Nó được lặp lại với bảng điều khiển, nhưng hiển nhiên nó hiển thị trong bảng điều khiển vì dấu gạch nối có trong DEBUG1. – Alasdair

+1

Mã hóa tệp .php của bạn là gì? Hãy thử chuyển đổi nó thành utf-8 mà không có BOM. – Hast

+0

... mh, hãy thử thêm setlocale (LC_ALL, 'en_US.UTF-8'); ở đầu trang – Federkun

Trả lời

5

Thay vì sử dụng strtoupper()/mb_strtoupper() hãy sử dụng mb_convert_case() vì chuyển đổi chữ hoa rất phức tạp trên các mã hóa khác nhau, cũng đảm bảo chuỗi của bạn là UTF-8.

$content = 'Le Courrier de Sáint-Hyácinthe'; 

mb_internal_encoding('UTF-8'); 
if(!mb_check_encoding($content, 'UTF-8') 
    OR !($content === mb_convert_encoding(mb_convert_encoding($content, 'UTF-32', 'UTF-8'), 'UTF-8', 'UTF-32'))) { 

    $content = mb_convert_encoding($content, 'UTF-8'); 
} 

// LE COURRIER DE SÁINT-HYÁCINTHE 
echo mb_convert_case($content, MB_CASE_UPPER, "UTF-8"); 

dụ làm việc: http://3v4l.org/enEfm#v443

Xem thêm nhận xét của tôi tại trang web PHP về bộ chuyển đổi: http://www.php.net/manual/function.utf8-encode.php#102382

+0

Tại sao 'á' là trong trường hợp thấp hơn trong đầu ra? – Hast

+0

@ Tôi không chắc chắn. Có lẽ chỉ ở ký tự tiếng Pháp mã hóa trường hợp trên á tồn tại? – powtac

+0

Tôi chỉ cần chạy một ví dụ từ câu hỏi trong bảng điều khiển của tôi và nó lặp lại: 'DEBUG2 LE COURRIER DE SÁINT-HYÁCINTHE' – Hast

2

Nó làm việc cho tôi, nhưng chỉ khi các tập tin php tự nó được lưu lại dưới dạng UTF -8 và khi thiết bị đầu cuối mà tôi dự kiến ​​là UTF-8. Tôi nghĩ điều gì đang xảy ra với bạn là tệp được lưu dưới dạng ISO-8859-1 và thiết bị đầu cuối của bạn đang mong chờ ISO-8859-1.

Đầu tiên, mb_detect_encodingkhông thực sự hoạt động cho chuỗi này. Ngay cả khi tệp PHP không phải là UTF-8, nó vẫn báo cáo nó là UTF-8.

Khi bạn in chuỗi chữ thường, nó in các ký tự ISO-8859-1 và thiết bị đầu cuối của bạn hiển thị chúng tốt. Sau đó, khi bạn chuyển đổi sang chữ hoa thường sử dụng UTF-8, nó sẽ bị xáo trộn.

Tôi đã tạo hai phiên bản của tệp này. Tôi đã lưu nó bằng cách sử dụng trình soạn thảo văn bản của tôi trong ISO-8859-1 là iso-8859-1.php. Sau đó, tôi sử dụng iconv để chuyển đổi toàn bộ tập tin sang UTF-8 và lưu nó như utf-8.php

iconv iso-8859-1.php --from iso-8859-1 --to UTF-8 > utf-8.php 

tôi đã thêm một dòng để in kết quả mã hóa mà mb_detect_encoding lợi nhuận.

$ file iso-8859-1.php 
iso-8859-1.php: PHP script, ISO-8859 text 

$ php iso-8859-1.php 
ENCODING: UTF-8 
DEBUG1 Le Courrier de S�int-Hy�cinthe 
DEBUG2 LE COURRIER DE S?INT-HY?CINTHE 

$ file utf-8.php 
utf-8.php: PHP script, UTF-8 Unicode text 

$ php utf-8.php 
ENCODING: UTF-8 
DEBUG1 Le Courrier de Sáint-Hyácinthe 
DEBUG2 LE COURRIER DE SÁINT-HYÁCINTHE 

Thiết bị đầu cuối của tôi thực sự mong đợi văn bản UTF-8, vì vậy khi tôi in văn bản ISO-8859-1 bị cắt xén. Mọi thứ hoạt động chính xác khi tệp được lưu dưới dạng utf-8 và thiết bị đầu cuối mong đợi utf-8.

+1

vì mb_detect_encoding không hoạt động, tôi kiểm tra xem chuỗi được mã hóa và giải mã lại vẫn là chuỗi gốc trong câu trả lời của tôi: http://stackoverflow.com/a/15051401/22470 – powtac

+0

OK. Nhưng tôi không thể làm điều này bởi vì chuỗi được đưa ra như là một đối số vào kịch bản PHP trên bàn điều khiển. Vì vậy, tôi cần một cách để buộc nó vào UTF-8 bằng cách nào đó từ bên trong kịch bản PHP đã có. – Alasdair

+0

Xem câu trả lời của tôi, tôi chuyển đổi chuỗi thành UTF-8 cho dù chuỗi đầu vào là gì ... – powtac

2

Trên thực tế, những gì làm việc ở đây chỉ đơn giản là

<?php 
mb_internal_encoding('UTF-8'); 

$x='Le Courrier de Sáint-Hyácinthe'; 
echo mb_strtoupper($x) . "\n"; 

đầu ra

LE COURRIER DE SÁINT-HYÁCINTHE 

đây nó hoạt động trực tiếp, nhưng có lẽ trong trường hợp của bạn, bạn cần phải thêm utf8_encode:

$x = utf8_encode('Le Courrier de Sáint-Hyácinthe'); 

- -

Một giải pháp thay thế hoạt động tại đây mà không có MB,

<?php 
echo strtoupper(str_replace('á', 'Á', 'Le Courrier de Sáint-Hyácinthe')); 
+0

Điều này chỉ hoạt động khi bạn có chuỗi đầu vào UTF-8 thích hợp. – powtac

+0

Đã chỉnh sửa câu trả lời. –

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