2008-09-29 46 views
21

Để chính xác hơn, tôi cần biết liệu (và nếu có thể) . Về cơ bản, tôi cần phải mở một cửa sổ bật lên để hiển thị một văn bản nhất định có thể chứa các ký tự byte kép, như tiếng Trung hoặc tiếng Nhật. Trong trường hợp này, chúng ta cần phải điều chỉnh kích thước cửa sổ hơn là cho tiếng Anh hoặc ASCII. Bất cứ ai cũng có một đầu mối?Làm thế nào để tìm xem liệu một chuỗi cụ thể có ký tự unicode hay không (đặc biệt là các ký tự Double Byte)

+0

Vâng, tôi dự kiến ​​điều này sẽ hoạt động. Nhưng nó không hoạt động trong IE. Tôi đoán một số vấn đề bố cục. Dù sao, kể từ khi mã để tính toán chiều dài văn bản được hiển thị và chiều cao/chiều rộng đã có, tôi đã đi trước với mã mà chỉ tìm thấy cho dù có một nhân vật byte đôi hay không. Và điều này đã được giải quyết. – Jay

+0

Với HTML5, bạn có thể sử dụng ngữ cảnh của phần tử Canvas ('var ctx = canvas.getContext ('2d')') để lấy chỉ số văn bản chiều rộng. 'var text_width = ctx.measureText (văn bản) .width;' Tôi không chắc phương thức này hoạt động tốt như thế nào với các ký tự unicode, và điều đáng tiếc là tất cả phương thức 'measureText' hiện đang trả về là chiều rộng. – WebWanderer

Trả lời

25

JavaScript giữ văn bản nội bộ là UCS-2, có thể mã hóa một tập hợp con khá rộng của Unicode.

Nhưng điều đó không thực sự nảy sinh đối với câu hỏi của bạn. Một giải pháp có thể là lặp qua chuỗi và kiểm tra mã ký tự tại mỗi vị trí:

function isDoubleByte(str) { 
    for (var i = 0, n = str.length; i < n; i++) { 
     if (str.charCodeAt(i) > 255) { return true; } 
    } 
    return false; 
} 

Điều này có thể không nhanh như bạn muốn.

+0

Tôi không biết JavaScript, nhưng không có nghĩa là UTF-16? Không có những thứ như UCS-16; có các dạng mã hóa UCS-x, giờ đã lỗi thời, theo tiêu chuẩn ISO/IEC 10646 tương đương với Unicode. UCS-2 sử dụng chính xác hai byte và do đó có thể đại diện cho 2^16 ký tự Unicode đầu tiên. UTF-16, ngược lại, sử dụng các đơn vị 16-bit, nhưng không nhất thiết phải là một đơn vị trong số đó. Tất cả các ký tự Unicode có thể được biểu diễn dưới dạng các chuỗi byte UTF-16. –

+0

Tôi tin bạn có nghĩa là UCS-2. –

+1

Tôi đã có nghĩa là UCS-2, cảm ơn bạn. – pcorcoran

0

Tại sao không để cửa sổ tự thay đổi kích thước dựa trên chiều cao/chiều rộng thời gian chạy?

Chạy một cái gì đó như thế này trong cửa sổ pop-up của bạn:

window.resizeTo(document.body.clientWidth, document.body.clientHeight); 
+0

Một cái gì đó như thế này nên làm việc trong các trường hợp không bệnh lý; tất nhiên bạn cần phải chắc chắn rằng bạn không vượt quá không gian màn hình có sẵn, hoặc ít nhất là giả định giới hạn hợp lý. – JasonTrue

6

Trên thực tế, tất cả các nhân vật là Unicode, ít nhất là từ quan điểm của động cơ Javascript.

Thật không may, sự hiện diện của các ký tự trong một phạm vi Unicode cụ thể sẽ không đủ để xác định bạn cần thêm dung lượng. Có một số ký tự chiếm khoảng không gian tương tự như các ký tự khác có các điểm mã Unicode cao hơn phạm vi ASCII. Dấu ngoặc kép, ký tự có dấu phụ, ký hiệu dấu chấm câu và ký hiệu tiền tệ khác nhau nằm ngoài phạm vi ASCII thấp và được phân bổ ở những nơi khá khác nhau trên mặt phẳng đa ngôn ngữ Unicode cơ bản.

Nói chung, các dự án mà tôi đã chọn lựa cung cấp thêm không gian cho tất cả ngôn ngữ hoặc đôi khi sử dụng javascript để xác định xem cửa sổ có thuộc tính css tự động cuộn thực sự có nội dung có chiều cao kích hoạt thanh cuộn hay không .

Nếu phát hiện sự hiện diện hoặc đếm, các ký tự CJK sẽ đủ để xác định bạn cần thêm một chút không gian, bạn có thể tạo một regex bằng các phạm vi sau: [\ u3300- \ u9fff \ uf900- \ ufaff] và sử dụng để trích xuất số lượng ký tự phù hợp. (Đây là một chút quá thô, và bỏ lỡ tất cả các trường hợp không BMP, có thể loại trừ một số phạm vi có liên quan khác, và rất có thể bao gồm một số ký tự không liên quan, nhưng đó là một điểm khởi đầu).

Một lần nữa, bạn sẽ chỉ có thể quản lý một heuristic thô mà không có gì đó dọc theo dòng của một công cụ hiển thị văn bản đầy đủ, bởi vì những gì bạn thực sự muốn là một cái gì đó giống như GDI's MeasureString (hoặc bất kỳ công cụ hiển thị văn bản khác tương đương) . Đã một thời gian kể từ khi tôi làm như vậy, nhưng tôi nghĩ tương đương HTML/DOM gần nhất là đặt chiều rộng trên div và yêu cầu chiều cao (cắt và dán lại, vì vậy xin lỗi nếu điều này có lỗi):

o = document.getElementById("test"); 

document.defaultView.getComputedStyle(o,"").getPropertyValue("height")) 
23

Tôi đã sử dụng câu trả lời mikesamuel cho câu trả lời này. Tuy nhiên, tôi nhận thấy có lẽ vì biểu mẫu này chỉ nên có một dấu gạch chéo thoát trước số u, ví dụ: \u và không phải \\u để thực hiện công việc này một cách chính xác.

function containsNonLatinCodepoints(s) { 
    return /[^\u0000-\u00ff]/.test(s); 
} 

trình cho tôi :)

+0

Chức năng của bạn tốt hơn nhiều so với câu trả lời được chọn, regex luôn tốt hơn – AmerllicA

1

Tôi đã làm chuẩn hai chức năng trong các câu trả lời trên và nghĩ rằng tôi sẽ chia sẻ các kết quả. Đây là mã kiểm tra tôi đã sử dụng:

const text1 = `The Chinese Wikipedia was established along with 12 other Wikipedias in May 2001. 中文維基百科的副標題是「海納百川,有容乃大」,這是中国的清朝政治家林则徐(1785年-1850年)於1839年為`; 

const regex = /[^\u0000-\u00ff]/; // Small performance gain from pre-compiling the regex 
function containsNonLatinCodepoints(s) { 
    return regex.test(s); 
} 

function isDoubleByte(str) { 
    for (var i = 0, n = str.length; i < n; i++) { 
     if (str.charCodeAt(i) > 255) { return true; } 
    } 
    return false; 
} 

function benchmark(fn, str) { 
    let startTime = new Date(); 
    for (let i = 0; i < 10000000; i++) { 
     fn(str); 
    } 
    let endTime = new Date(); 

    return endTime.getTime() - startTime.getTime(); 
} 

console.info('isDoubleByte => ' + benchmark(isDoubleByte, text1)); 
console.info('containsNonLatinCodepoints => ' + benchmark(containsNonLatinCodepoints, text1)); 

Khi chạy này tôi nhận:

isDoubleByte => 2421 
containsNonLatinCodepoints => 868 

Vì vậy cho chuỗi đặc biệt này là giải pháp regex là khoảng 3 lần nhanh hơn.

Tuy nhiên, lưu ý rằng đối với chuỗi có ký tự đầu tiên là unicode, isDoubleByte() trả về ngay lập tức và nhanh hơn nhiều so với regex (vẫn có phần trên của cụm từ thông dụng).

Ví dụ cho chuỗi 中国, tôi có những kết quả này:

isDoubleByte => 51 
containsNonLatinCodepoints => 288 

Để tận dụng tốt nhất của cả hai thế giới, nó có thể là tốt hơn để kết hợp cả hai:

var regex = /[^\u0000-\u00ff]/; // Small performance gain from pre-compiling the regex 
function containsDoubleByte(str) { 
    if (!str.length) return false; 
    if (str.charCodeAt(0) > 255) return true; 
    return regex.test(str); 
} 

Trong trường hợp đó, nếu ký tự đầu tiên là tiếng Trung Quốc (có khả năng nếu toàn bộ văn bản là tiếng Trung Quốc), hàm sẽ nhanh và quay lại ngay lập tức. Nếu không, nó sẽ chạy regex, mà vẫn còn nhanh hơn kiểm tra từng nhân vật riêng lẻ.

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