2008-10-14 30 views
6

Sự khác biệt giữa UTF và UCS là gì.Sử dụng UTF trong mã C++

Cách tốt nhất để thể hiện không phải là bộ ký tự châu Âu (sử dụng UTF) trong chuỗi C++. Tôi muốn biết các khuyến nghị của bạn cho:

  • đại diện nội bộ bên trong mã
    • Đối với thao tác chuỗi tại thời gian chạy
    • Để sử dụng các chuỗi cho mục đích hiển thị.
  • đại diện lưu trữ tốt nhất (tức Trong tập tin)
  • nhất trên định dạng phương tiện giao thông dây (Chuyển giữa các ứng dụng mà bạn có thể về kiến ​​trúc khác nhau và có một miền địa phương tiêu chuẩn khác nhau)

Trả lời

8

Sự khác biệt giữa UTF và UCS là gì.

Mã hóa UCS có chiều rộng cố định và được đánh dấu bằng số byte được sử dụng cho mỗi ký tự. Ví dụ, UCS-2 yêu cầu 2 byte cho mỗi ký tự. Các ký tự có điểm mã ngoài phạm vi có sẵn không thể được mã hóa bằng mã hóa UCS.

Mã hóa UTF có chiều rộng thay đổi và được đánh dấu bằng số bit tối thiểu để lưu trữ một ký tự. Ví dụ, UTF-16 yêu cầu ít nhất 16 bit (2 byte) cho mỗi ký tự. Các ký tự có các điểm mã lớn được mã hóa bằng cách sử dụng số byte lớn hơn - 4 byte cho các ký tự astral trong UTF-16.

  • đại diện nội bộ bên trong mã
  • đại diện lưu trữ tốt nhất (ví dụ: Trong tập tin)
  • nhất trên định dạng phương tiện giao thông dây (Chuyển giữa các ứng dụng có thể được trên kiến ​​trúc khác nhau và có một miền địa phương tiêu chuẩn khác nhau)

Đối với hệ thống hiện đại, mã hóa lưu trữ và vận chuyển hợp lý nhất là UTF-8. Có những trường hợp đặc biệt mà những người khác có thể thích hợp - UTF-7 cho các máy chủ thư cũ, UTF-16 cho các trình soạn thảo văn bản kém được viết - nhưng UTF-8 là phổ biến nhất.

Biểu diễn nội bộ ưu tiên sẽ tùy thuộc vào nền tảng của bạn. Trong Windows, nó là UTF-16. Trong UNIX, nó là UCS-4. Mỗi điểm có các điểm tốt:

  • Chuỗi UTF-16 không bao giờ sử dụng nhiều bộ nhớ hơn chuỗi UCS-4. Nếu bạn lưu trữ nhiều chuỗi lớn với các ký tự chủ yếu trong mặt phẳng đa ngôn ngữ cơ bản (BMP), UTF-16 sẽ yêu cầu ít không gian hơn UCS-4. Bên ngoài BMP, nó sẽ sử dụng cùng một số tiền.
  • UCS-4 dễ hiểu hơn. Bởi vì các ký tự UTF-16 có thể được chia thành nhiều "cặp thay thế", nên có thể khó phân tách chính xác hoặc hiển thị một chuỗi. Văn bản UCS-4 không có vấn đề này. UCS-4 cũng hoạt động giống như văn bản ASCII trong mảng "char", vì vậy các thuật toán văn bản hiện tại có thể được chuyển dễ dàng.

Cuối cùng, một số hệ thống sử dụng UTF-8 làm định dạng nội bộ. Điều này là tốt nếu bạn cần liên kết với các hệ thống dựa trên ASCII hoặc ISO-8859 hiện tại vì các byte NULL không có mặt ở giữa văn bản UTF-8 - chúng nằm trong UTF-16 hoặc UCS-4.

+1

Không, mã hóa UTF không phải lúc nào cũng có chiều rộng thay đổi (ví dụ như UTF-32). – bortzmeyer

+0

Utf-32 có thể sử dụng chiều rộng cố định cho mỗi điểm mã, nhưng tôi nghĩ * bạn vẫn có thể có (và cần chấp nhận và bình thường hóa một codepoint) nhiều điểm (khi bạn kết hợp các ký tự) đại diện cho một char/glyph hoàn chỉnh. Nếu vậy, UTF-32 không thực sự tốt hơn UTF-16. – Shadow2531

+1

@bortzmeyer: UTF-32 thực sự chỉ là UCS-4 với một vài hạn chế bổ sung. Thành thật mà nói, tôi chưa bao giờ thấy UTF-32 được sử dụng * bất cứ nơi nào *, vì vậy tôi có xu hướng bỏ qua nó. –

0

UTC được Coordinated Universal Time, không phải là một bộ ký tự (tôi không tìm thấy bất kỳ bộ ký tự nào được gọi là UTC).

Đối với đại diện nội bộ, bạn có thể muốn sử dụng wchar_t cho mỗi ký tự và std :: wstring cho chuỗi. Chúng sử dụng chính xác 2 byte cho mỗi ký tự, do đó việc tìm kiếm và truy cập ngẫu nhiên sẽ nhanh chóng.

Để lưu trữ, nếu hầu hết dữ liệu không phải là ASCII (ví dụ: mã> = 128), bạn có thể muốn sử dụng UTF-16 gần như giống như được biên tập wstringwchar_t.

Vì UTF-16 có thể là ít endian hoặc lớn endian, cho vận chuyển dây, cố gắng chuyển đổi nó sang UTF-8, đó là kiến ​​trúc độc lập.

+0

Kích thước của wchar_t (và do đó không phải là wstring) không được định nghĩa Tôi đã thấy cả hai phiên bản 2 và 4 byte. Tại sao UTS-16 để lưu trữ nhưng UTF-8 cho các tệp (Tệp có thể được lưu trên một máy và được tải trên một máy khác). Tôi muốn hiểu tại sao bạn chọn lựa cũng như lựa chọn. –

+0

http://en.wikipedia.org/wiki/Universal_Character_Set –

+0

@Martin: UTF-16 không thể được xử lý bởi các công cụ định hướng ASCII hiện tại vì nhiều byte là 0, làm cho các hàm per-byte tin rằng đã đạt được điểm kết thúc NULL. –

2

tôi sẽ đề nghị:

  • Đối với đại diện trong mã, wchar_t hoặc tương đương.
  • Đối với đại diện lưu trữ, UTF-8.
  • Đối với biểu diễn dạng dây, UTF-8.

Ưu điểm của UTF-8 trong lưu trữ và tình huống dây là độ bền máy không phải là yếu tố. Lợi thế của việc sử dụng ký tự kích thước cố định chẳng hạn như wchar_t trong mã là bạn có thể dễ dàng tìm ra độ dài của chuỗi mà không cần phải quét nó.

+0

wchar_t: Nhưng mã hóa nào? Bạn đang đề xuất UTF-16 nội bộ? –

+0

Trên nhiều nền tảng Unix, wchar_t là 32 bit, vì vậy điều này rất dễ dàng. Trên nền tảng nơi wchar_t là 16 bit, có, UTF-16 sẽ là con đường để đi. –

+0

Martin: Tôi đã khôi phục bản chỉnh sửa của bạn vì sử dụng wchar_t không ngụ ý UTF-16 - trong UNIX, sizeof (wchar_t) == 4. –

0

Trong đại diện nội bộ bên trong mã này, bạn nên làm điều này cho cả hai nhân vật châu Âu và ngoài châu Âu:

\ uNNNN

Nhân vật trong phạm vi \ u0020 để \ u007E, và một chút của khoảng trắng (ví dụ như cuối dòng) có thể được viết như các ký tự thông thường. Bất cứ điều gì ở trên \ u0080, nếu bạn viết nó như một nhân vật bình thường thì nó sẽ chỉ biên dịch trong trang mã của bạn (ví dụ: OK ở Pháp nhưng phá ở Nga, OK ở Nga nhưng phá vỡ ở Nhật, OK ở Trung Quốc nhưng phá ở Mỹ, vv .).