Bukharbaeva N.A. Mã hóa thông tin văn bản

  1. Hãy lấy trang web của chúng tôi làm ví dụ: www.yourmaster.ru
  2. Tất cả các văn bản trang web được viết và đăng trên trang web dưới dạng mã hóa "windows-1251" và trình duyệt không được thông báo về điều này
  3. Máy chủ lưu trữ tự động gửi tiêu đề sau theo mặc định:
    Loại nội dung: văn bản/html; bộ ký tự=utf-8

Nếu có sự khác biệt như vậy trong mã hóa thực tế của trang web và thông tin mã hóa trong tiêu đề do máy chủ gửi, vấn đề sẽ phát sinh trong việc hiển thị các trang của trang web trong trình duyệt của khách truy cập.

Mã hóa chính xác là rất quan trọng!

Hãy thử giải thích tại sao.

Với các cài đặt được mô tả ở trên, trình duyệt của người dùng sẽ không thể tự động xác định văn bản trên trang web đang xem được viết bằng mã hóa nào. Và rất có thể nó sẽ hiển thị các trang lộn xộn không thể đọc được. Nếu bạn gặp phải "thông tin sai lệch" như vậy giữa trình duyệt và trang web của mình thì bạn cần khẩn trương thực hiện hành động thích hợp. Nếu không, điều này rất có thể sẽ dẫn đến một loạt vấn đề nghiêm trọng.

Trước hết, trong điều kiện và cài đặt trang web như vậy, khách truy cập sẽ phải liên tục thủ công (sử dụng phương pháp lựa chọn) chỉ định mã hóa để trình duyệt hiển thị trang web. Để làm điều này bạn sẽ cần thực hiện một số số lần nhấp chuột thêm chuột. Nhưng bạn phải thừa nhận rằng, không phải ai cũng muốn thực hiện thêm 2-3 cú click chuột chỉ để xem thông tin trên trang. dạng có thể đọc được. Hơn nữa, nhiều người thậm chí không chỉ biết cách thay đổi mã hóa hiển thị trong cài đặt trình duyệt mà còn không biết mã hóa nói chung là gì! Hầu hết khách truy cập có thể quyết định rằng trang web bị chủ sở hữu bỏ rơi hoặc bị ai đó tấn công và sẽ cố gắng không quay lại trang đó nữa.

Thứ hai, nếu có định nghĩa mơ hồ về mã hóa trang của trang web, công cụ tìm kiếm có thể lập chỉ mục không chính xác nội dung văn bản của trang web. Điều đó lần lượt mang lại vấn đề nghiêm trọng với lưu lượng truy cập của người dùng từ các công cụ tìm kiếm. Tất nhiên, một số công cụ tìm kiếm có thể cố gắng bằng cách nào đó xác định mã hóa chính xác từ nội dung của các trang, nhưng điều này không làm cho việc này dễ dàng hơn nhiều. Theo quy định, vấn đề vẫn còn.

Tôi hy vọng bạn đã nhận ra rằng các vấn đề về mã hóa có thể trở thành một trở ngại rất nghiêm trọng đối với hoạt động của trang web, sự phát triển và thu hút khách truy cập thường xuyên vào trang web.

Để vấn đề tương tự không có vấn đề gì với việc mã hóa, bạn cần thực hiện các cài đặt phù hợp cả trên máy chủ lưu trữ và trên các trang của trang web.

Cài đặt trang web phải sao cho mọi trình duyệt hoặc bất kỳ robot nào máy tìm kiếm có thể xác định rõ ràng cách mã hóa thông tin từ trang web được truyền đi!

Giải quyết vấn đề mã hóa trang web

Chúng tôi đã nhận thấy rằng tất cả văn bản trên trang web của chúng tôi đều được viết và truyền tới trình duyệt của khách truy cập trang web ở dạng mã hóa “windows-1251”. Chúng tôi có thể làm gì để máy chủ lưu trữ trang web của chúng tôi truyền tới trình duyệt trong tiêu đề Thông tin chính xác về mã hóa? Hãy tiến hành theo thứ tự...

1. Để không phụ thuộc vào cài đặt máy chủ, trên tất cả các trang của trang web, trực tiếp trong mã HTML, bạn cần viết rõ ràng lệnh sau bằng thẻ meta:

Nó phải được đặt trên tất cả các trang, tốt nhất là ngay sau thẻ mở . Điều này sẽ cho phép trình duyệt tự động chọn mã hóa hiển thị chính xác khi tải và giải thích trang theo chỉ thị nhận được! Chỉ thị này thôi cũng đủ để giải quyết vấn đề của chúng tôi. Nhưng đó là cách nó được dự định trên lý thuyết. Nhưng trên thực tế, chỉ thị này không phải lúc nào cũng đủ. TRONG Trong một số ít trường hợp, nhưng điều đó xảy ra là trình duyệt chọn làm mã hóa để hiển thị trang không phải là trang được chỉ định trong lệnh trên chính trang đó mà là trang được truyền trong tiêu đề từ máy chủ! Và nếu thông tin mã hóa được chỉ định ở hai nơi không khớp nhau thì vấn đề có thể vẫn còn.

2. Để máy chủ cung cấp thông tin mã hóa chính xác trong phản hồi của nó, bạn cần tạo một tệp trong thư mục gốc của trang web .htaccess và viết chỉ thị trong đó:

Thêm bộ ký tự mặc định windows-1251

Sau đó, máy chủ sẽ tiếp tục gửi tiêu đề mã hóa theo mặc định, nhưng tên của mã hóa sẽ khớp với tên có hiệu lực trên chính trang web đó. Sẽ không còn bất kỳ sự khác biệt nào trong tên gọi.

Nếu tập tin .htaccessđã tồn tại trên máy chủ của bạn, thì chỉ cần thêm lệnh được chỉ định, chẳng hạn như ngay từ đầu. Và trong mọi trường hợp, bạn không nên xóa thông tin đã tồn tại trong đó một cách không cần thiết!

Đó là giải pháp cho vấn đề. Đồng ý, tất cả điều này không quá khó?! Nhưng nó rất hữu ích để ngăn chặn mọi vấn đề với mã hóa khét tiếng.

Bằng cách thực hiện liên tiếp hai khuyến nghị nêu trên, trình duyệt chắc chắn sẽ không thể mắc lỗi trong lựa chọn tự động mã hóa chính xác để hiển thị thông tin trên trang web của bạn. Rốt cuộc, chúng tôi đã chỉ ra thông tin mã hóa một cách rõ ràng, chính xác và thậm chí theo hai chỉ thị khác nhau!

Tình huống đặc biệt

Tình huống một

Những người tạo ra trang web và thường không phải là chính khách hàng, bắt đầu thực hiện một số sửa đổi nhất định một cách tùy tiện và thiếu suy nghĩ đối với trang web, đặt văn bản theo ý muốn, v.v. Đến mức, kết quả là họ có thể truy cập trang web phần có thông tin trong mã hóa khác nhau . Chúng ta không thể nói nó là gì cách tiếp cận đúng đắn, nhưng chúng tôi sẽ đẩy lùi vì điều này xảy ra và thế thôi. Trong trường hợp này, ngay cả khi chúng tôi làm theo hai khuyến nghị được liệt kê ở trên, một tình huống vẫn có thể phát sinh khi máy chủ cung cấp thông tin về một mã hóa và trong mã trang HTML một mã hóa khác sẽ được chỉ định rõ ràng. Trong trường hợp như vậy, có lẽ điều tốt nhất giải pháp đơn giản sẽ như sau.

Viết vào tập tin .htaccess chỉ thị:

AddDefaultCharset Tắt

Khi sử dụng lệnh này, máy chủ sẽ không gửi tiêu đề có thông tin về mã hóa của trang được truyền. Sau đó, các trình duyệt sẽ bắt đầu từ dữ liệu mã hóa, được biểu thị rõ ràng trong mã HTML trên chính các trang của trang web. Hơn nữa, trên một trang dữ liệu có thể được mã hóa windows-1251 và trên một trang khác, ví dụ như trong utf-8. Điều chính là không quên chỉ ra trên các trang này các thẻ meta thích hợp với thông tin về mã hóa chính xác để trình duyệt nhận dạng và hiển thị văn bản.

Mặc dù giải pháp như vậy là đơn giản nhất nhưng có lẽ nó không phải là giải pháp tối ưu và đúng đắn nhất. Theo cách tốt, bạn cần đặt tất cả thông tin trên trang web và trong tất cả các phần của trang web theo cùng một mã hóa! Và nếu có một số trang được mã hóa khác nhau, tốt hơn là bạn nên cập nhật thông tin trong đó bằng cách chuyển đổi tất cả văn bản sang mã hóa cần thiết.

Tình huống hai

Như bạn đã biết, khi tạo trang, hầu hết các trang đều chọn một phần dữ liệu từ cơ sở dữ liệu, ví dụ: MySQL (nếu trang được viết bằng Ngôn ngữ PHP). Thường, Tạidi chuyển một trang web từ hosting này sang hosting khác, vấn đề có thể phát sinh do mã hóa không khớp giữa dữ liệu được lưu trữ trong cơ sở dữ liệu Dữ liệu MySQL và dữ liệu được lưu trữ, ví dụ: trực tiếp trong các mẫu trang web. Do đó, có thể nảy sinh tình huống khi tạo một trang, nó có thể chứa dữ liệu ở các bảng mã khác nhau. Đây có lẽ là một trong những điều thô lỗ nhất lỗi có thể xảy ra với mã hóa trên trang web và nó cần được giải quyết ngay lập tức. Nếu không, những khó khăn bổ sung có thể phát sinh sau này khi điền và chỉnh sửa trang web.

Việc giải quyết những bất đồng như vậy với dữ liệu được lưu trữ trong cơ sở dữ liệu có thể đạt được bằng cách thiết lập chính xác các cài đặt mã hóa một cách rõ ràng khi kết nối với cơ sở dữ liệu và trước khi truy xuất dữ liệu từ nó. Ví dụ: nếu dữ liệu trên trang web của chúng tôi được lưu trữ ở dạng mã hóa windows-1251 thì chúng tôi phải đọc dữ liệu từ cơ sở dữ liệu ở cùng một mã hóa. Để làm điều này, sau khi kết nối với cơ sở dữ liệu bằng cách sử dụng Hàm PHP mysql_connect() (hoặc mysql_pconnect()) làm yêu cầu tiếp theo SQL:

mysql_query("THIẾT LẬP TÊN cp1251");

Yêu cầu này, báo cho máy chủ cơ sở dữ liệu MySQL biết rằng tất cả dữ liệu được lưu trữ và phải được truyền dưới dạng mã hóa cp1251 (đây là tên mã hóa được sử dụng trong MySQL thay vì tên windows-1251 đã đề cập trước đó, được sử dụng khi truyền dữ liệu HTML).

Nhưng cách tốt nhất là thay đổi mã hóa dữ liệu thành Cơ sở dữ liệu MySQLđến cái được sử dụng trên chính trang web đó. Khi đó máy chủ cơ sở dữ liệu sẽ không phải thực hiện thao tác không cần thiết để chuyển đổi dữ liệu từ định dạng này sang định dạng khác.

Trên một ghi chú

Nếu bạn đã truy cập một trang web có mã hóa bị lỗi vì lý do nào đó nhưng bạn thực sự cần phải lấy nó thông tin hữu ích(không cần đợi nhà phát triển trang web làm theo các đề xuất mà chúng tôi đã liệt kê ở trên), bạn nên chỉ định thủ công mã hóa trang chính xác trong cài đặt trình duyệt. Điều này thường có thể được thực hiện thông qua menu trình duyệt chính: Xem -> Mã hóa-> Tiếp theo, chọn tên mã hóa trang dự định từ danh sách. Có lẽ, để đoán, bạn sẽ phải thực hiện thủ tục này nhiều lần, chọn tên này hoặc tên khác từ danh sách mã hóa. Để tăng tốc quá trình lựa chọn, chúng tôi khuyên bạn nên thực hiện theo thứ tự sau: Chữ Cyrillic (Windows-1251), chữ cái Cyrillic (UTF-8), Chữ Cyrillic (KOI)8-R). Đây là những mã hóa được sử dụng phổ biến nhất trên các trang web trên RuNet.

Trong hai năm qua, đã có một số tiến bộ đáng chú ý trong việc xây dựng các mã sửa lỗi. Người ta đã tìm thấy các phương pháp để xây dựng các mã rất dài và hiệu quả; và quan trọng nhất, những mã này hóa ra lại phù hợp với triển khai thực tế. Đồng thời, nhu cầu ngày càng tăng về các kênh liên lạc có độ tin cậy rất cao, có thể được sử dụng trong các tổ hợp máy tính và nhiều loại khác nhau. thiết bị tự động. Khi nhu cầu về độ tin cậy cao hơn tăng lên thì hiệu quả chi phí của thiết bị điện tử cũng tăng theo. thiết bị logic và lý thuyết mã hóa đang được phát triển sâu hơn, đã đến lúc các thiết bị phát hiện và sửa lỗi, tức là các thiết bị thuộc loại được mô tả trong cuốn sách này, sẽ ngày càng trở nên quan trọng. vai trò quan trọng trong việc tạo ra các hệ thống thông tin phức tạp.

Chương này giới thiệu khái niệm về kênh liên lạc, mô tả vai trò của mã trong việc truyền thông tin và định nghĩa mã khối và các khái niệm quan trọng khác được giới thiệu.

1.1. liên kết

Sơ đồ hệ thống kỹ thuật số kết nối được hiển thị trong hình. 1.1. Mô hình tương tự cũng mô tả hệ thống lưu trữ thông tin, nếu môi trường lưu trữ thông tin được coi là một kênh. Một kênh điển hình để truyền thông tin là kênh điện thoại. Thiết bị điển hìnhđể lưu trữ thông tin là một máy ghi băng, bao gồm cả đầu ghi và đầu đọc.

Cơm. 1.1. Sơ đồ khối hệ thống chung chuyển hoặc lưu trữ thông tin.

Nguồn thông tin điển hình là một tin nhắn bao gồm các chữ số nhị phân hoặc thập phân hoặc văn bản được viết bằng bảng chữ cái. Bộ mã hóa chuyển đổi các tin nhắn này thành tín hiệu có thể được truyền đi

theo kênh. Tín hiệu điển hình là tín hiệu điện với một số hạn chế về công suất, băng thông và thời lượng. Những tín hiệu này đi vào kênh và bị méo do nhiễu. Sau đó, tín hiệu bị biến dạng đi vào thiết bị giải mã, thiết bị này sẽ tái tạo lại tin nhắn đã gửi và chuyển tiếp đến người nhận. Nhiệm vụ của kỹ sư viễn thông chủ yếu là xây dựng bộ mã hóa và giải mã, mặc dù nó cũng có thể bao gồm nhiệm vụ cải thiện chính kênh đó. Lưu ý rằng bộ mã hóa bao gồm một thiết bị thực hiện thao tác thường được gọi là điều chế và bộ giải mã bao gồm một thiết bị thực hiện phát hiện.

Hệ thống được hiển thị trong Hình. 1.1 quá chung chung để có thể sử dụng thuận tiện trong phân tích lý thuyết. Lý thuyết mã hóa tổng quát chỉ ra rằng một kênh truyền thông có dung lượng nhất định, các nguồn điển hình có tốc độ tạo thông tin nhất định và trong trường hợp tốc độ tạo thông tin của một nguồn nhỏ hơn băng thông kênh, mã hóa và giải mã có thể được thực hiện sao cho xác suất giải mã sai nhỏ tùy ý.

Cơm. 1.2, Sơ đồ khối hệ thống điển hình chuyển hoặc lưu trữ thông tin.

Vì vậy, mặc dù vẫn còn hy vọng cho tương lai nhưng hiện tại lý thuyết này chỉ cung cấp những dấu hiệu mơ hồ về cách thiết kế một hệ thống truyền tải thông tin.

Đặc trưng hệ thống hiện đại truyền tải thông tin được thể hiện trong hình. 1.2. Gần như tất cả máy tính chuyển đổi thông tin đến thành nhị phân và sau đó xử lý nó ở dạng nhị phân. Nhiều hệ thống sử dụng mã trong đó có nhiều

sự kết hợp của sáu ký tự nhị phân biểu thị số, chữ cái, dấu cách và các ký tự đặc biệt như dấu chấm câu. Một mã phổ biến khác sử dụng bốn chữ số nhị phân cho mỗi chữ số thập phân và hai chữ số thập phân cho mỗi ký tự chữ cái hoặc ký tự đặc biệt.

Một thiết bị mã hóa các ký hiệu nhị phân thành tín hiệu ở đầu vào của kênh đôi khi được gọi là bộ điều biến. Trong hầu hết các trường hợp, nó liên kết số một với xung và số 0 với việc không có xung hoặc xung có thể phân biệt rõ ràng với mã cho một xung. Việc chuyển đổi riêng biệt từng ký tự nhị phân này là một hạn chế chắc chắn làm giảm thông lượng kênh. Bộ giải mã xác định xem xung nhận được tiếp theo là 0 hay 1. Giải mã các xung riêng lẻ dẫn đến giảm thông lượng hơn nữa. Lý thuyết cho thấy hơn phương pháp phức tạp mã hóa và giải mã tăng tốc độ truyền với cùng xác suất lỗi. Tuy nhiên, người ta vẫn chưa biết cách hiệu quả việc thực hiện các phương pháp này.

Các thiết bị sử dụng nhị phân để mã hóa và giải mã các ký tự nhị phân. mã nhị phân, phát hiện và sửa lỗi.

Nếu chuỗi bit trông không hợp lý (theo quan điểm của con người), thì đây là trường hợp tài liệu rất có thể bị chuyển đổi sai ở một thời điểm nào đó. Ví dụ: chúng tôi lấy văn bản ÉGÉìÉRÅ[ÉfÉBÉìÉOÇÕìÔǵÇ≠ǻǢ và không nghĩ ra điều gì tốt hơn, hãy lưu nó ở dạng UTF-8. Trình soạn thảo văn bản cho rằng nó đọc chính xác văn bản bằng mã hóa Mac Roman và bây giờ nó cần được lưu ở một mã hóa khác. Rốt cuộc, tất cả các ký tự này đều hợp lệ trong Unicode. Ý tôi là, Unicode có mệnh đề cho É, cho G, v.v. Vì vậy chúng tôi chỉ lưu nó dưới dạng UTF-8:

11000011 10001001 01000111 11000011 10001001 11000011 10101100 11000011 10001001 01010010 11000011 10000101 01011011 11000011 10001001 01100110 11000011 10001001 01000010 11000011 10001001 11000011 10101100 11000011 10001001 01001111 11000011 10000111 11000011 10010101 11000011 10101100 11000011 10010100 11000011 10000111 11000010 10110101 11000011 10000111 11100010 10001001 10100000 11000011 10000111 11000010 10111011 11000011 10000111 11000010 10100010

Đây là cách văn bản ÉGÉìÉRÅ[ÉfÉBÉìÉOÇÕìÔǵÇ≠ǻǢ hiện được biểu diễn dưới dạng một chuỗi các bit UTF-8. Chuỗi bit này hoàn toàn khác với những gì có trong tài liệu gốc. Cho dù chúng ta sử dụng mã hóa nào để mở chuỗi này, chúng ta sẽ không bao giờ nhìn thấy văn bản gốc エンコーディングは難しくない. Anh ấy vừa mới bị lạc. Nó có thể được khôi phục nếu chúng tôi biết mã hóa Shift-JIS ban đầu và chúng tôi xử lý văn bản dưới dạng Mac Roman rồi lưu nó dưới dạng UTF-8. Nhưng những điều kỳ diệu như vậy rất hiếm.

Nhiều khi một chuỗi bit cụ thể không chính xác trong một mã hóa cụ thể. Nếu chúng ta cố mở tài liệu gốc ở dạng ASCII, chúng ta sẽ thấy rằng một số ký tự được nhận dạng, nhưng một số ký tự khác thì không. Chương trình bạn đang sử dụng có thể quyết định loại bỏ các byte không phù hợp với mã hóa hiện tại hoặc thay thế chúng bằng dấu chấm hỏi. Hoặc tại tính cách đặc biệt Thay thế Unicode: � (U+ FFFD). Nếu bạn lưu tài liệu sau quá trình xóa các ký tự không phù hợp, bạn sẽ mất chúng vĩnh viễn.

Nếu bạn đoán sai mã hóa rồi lưu nó vào một mã khác, bạn sẽ làm hỏng tài liệu. Bạn có thể cố gắng khắc phục nhưng những nỗ lực này thường không thành công. Phép thuật lệch bit thường vẫn là phép thuật bị hỏng: giống như thuốc đắp cho người chết.

Và làm thế nào để thay đổi mã hóa một cách chính xác?

Nó thực sự đơn giản! Bạn cần biết cách mã hóa một đoạn văn bản cụ thể (chuỗi bit) và sử dụng nó để giải mã nó. Thats tất cả để có nó. Nếu bạn đang viết một chương trình nhận văn bản từ người dùng, hãy xác định xem chương trình sẽ thực hiện việc này bằng cách mã hóa nào. Bất kỳ trường văn bản nào cũng phải biết nó chấp nhận dữ liệu ở dạng mã hóa nào. Đối với bất kỳ loại tệp nào mà người dùng có thể tải vào chương trình, phải xác định mã hóa. Hoặc nên có cách nào đó để hỏi người dùng về nó. Thông tin có thể được cung cấp bởi định dạng tệp hoặc người dùng (tất nhiên hầu hết trong số họ khó có thể biết cho đến khi họ đọc xong bài viết).

Nếu bạn cần chuyển đổi văn bản từ bảng mã này sang bảng mã khác, hãy sử dụng những công cụ đặc biệt. Chuyển đổi là công việc tẻ nhạt khi so sánh hai trang mã và quyết định ký tự 152 trong mã hóa A giống với ký tự 4122 trong mã hóa B, sau đó thay đổi các bit. Không cần phải phát minh lại bánh xe: mọi ngôn ngữ lập trình phổ biến đều có các công cụ trừu tượng hóa bit và trang mã để chuyển đổi văn bản từ mã hóa sang mã hóa.

Giả sử ứng dụng của bạn cần chấp nhận các tệp ở GB18030, nhưng nội bộ bạn đang chạy ở UTF-32. Công cụ iconv có thể thực hiện chuyển đổi trong một dòng: iconv("GB18030", "UTF-32", $string). Các ký tự sẽ vẫn giữ nguyên mặc dù cách biểu diễn bit đã thay đổi.

ký tự mã hóa GB18030 mã hóa UTF-32
縧 10111111 01101100 00000000 00000000 01111110 00100111

Đó là tất cả. Nội dung của chuỗi theo cách hiểu của con người không thay đổi nhưng giờ đây nó là chuỗi UTF-32 hợp lệ. Nếu bạn tiếp tục làm việc với nó trong UTF-32, bạn sẽ không gặp bất kỳ vấn đề nào với các ký tự không thể đọc được. Tuy nhiên, như chúng ta đã thảo luận trước đó, không phải tất cả các bảng mã đều có khả năng hiển thị tất cả các ký tự. Không thể mã hóa ký tự 縧 bằng bất kỳ bảng mã ngôn ngữ châu Âu nào. Và điều gì đó khủng khiếp có thể xảy ra.

Mọi thứ đều ở dạng Unicode

Đây là lý do tại sao không có lý do gì trong thế kỷ 21 không sử dụng Unicode. Một số bảng mã chuyên dụng cho các ngôn ngữ Châu Âu có thể có hiệu suất cao hơn Unicode dành riêng cho ngôn ngữ. Nhưng miễn là bạn không phải làm việc với hàng terabyte văn bản đặc biệt (rất RẤT NHIỀU), bạn không phải lo lắng về điều đó. Các vấn đề phát sinh từ việc mã hóa không tương thích còn tệ hơn nhiều so với việc mất một gigabyte. Và lập luận này sẽ chỉ trở nên mạnh mẽ hơn khi việc lưu trữ dữ liệu và độ rộng kênh ngày càng tăng và trở nên rẻ hơn.

Nếu hệ thống cần hoạt động với các bảng mã khác, trước tiên hãy chuyển đổi văn bản sang Unicode và chuyển đổi lại nếu bạn cần xuất nó ở đâu đó. Nếu không, bạn sẽ phải theo dõi rất cẩn thận từng trường hợp truy cập dữ liệu và thực hiện các chuyển đổi cần thiết, nếu có thể mà không làm mất thông tin.

Tai nạn hạnh phúc
Tôi đã có một trang web được kết nối với cơ sở dữ liệu. Ứng dụng của tôi xử lý mọi thứ dưới dạng UTF-8 và lưu trữ nó trong cơ sở dữ liệu như vậy, mọi thứ đều tuyệt vời, nhưng khi tôi vào khu vực quản trị cơ sở dữ liệu, tôi không thể hiểu được gì.
- lập trình viên lỗ mãng ẩn danh

Các tình huống phát sinh khi mã hóa được xử lý không chính xác nhưng mọi thứ vẫn hoạt động tốt. Điều thường xảy ra là mã hóa cơ sở dữ liệu được đặt thành latin-1, nhưng ứng dụng hoạt động với UTF-8 (hoặc bất kỳ loại nào khác). Nói chung, mọi sự kết hợp giữa 1 và 0 đều hợp lệ trong tiếng Latin-1 byte đơn. Nếu cơ sở dữ liệu nhận được dữ liệu từ một ứng dụng như 11100111 10111000 10100111 thì nó sẽ vui vẻ lưu dữ liệu đó vì nghĩ rằng ứng dụng đó có nghĩa là 縧. Tại sao không? Sau đó, cơ sở dữ liệu trả về các bit tương tự cho ứng dụng, điều này rất vui vì nó đã nhận được ký tự UTF-8 縧 như dự kiến. Nhưng giao diện quản trị cơ sở dữ liệu biết rằng Latin-1 được sử dụng và đây là kết quả: không thể hiểu được gì.
Kẻ ngốc chỉ đơn giản là trúng xổ số, mặc dù các ngôi sao không đứng về phía anh ta. Mọi thao tác trên văn bản trong cơ sở dữ liệu đều có thể hoạt động nhưng có thể không được thực hiện như dự định do cơ sở dữ liệu không nhận biết chính xác văn bản. Trong trường hợp xấu nhất, cơ sở dữ liệu sẽ vô tình hủy toàn bộ văn bản, thực hiện thao tác tùy ý sau 2 năm cài đặt do mã hóa sai (và tất nhiên là không có bản sao lưu cho bạn).

UTF-8 và ASCII

Ưu điểm của UTF-8 là khả năng tương thích nhị phân của nó với ASCII, đây là cơ sở thực tế cho tất cả các bảng mã. Tất cả ký tự ASCII chiếm tối đa byte trong UTF-8 và sử dụng các bit giống như trong ASCII. Nói cách khác, ASCII có thể được ánh xạ 1:1 sang UTF-8. Bất kỳ ký tự không phải ASCII nào cũng chiếm 2 byte trở lên trong UTF-8. Hầu hết các ngôn ngữ lập trình sử dụng ASCII làm mã hóa mã nguồn đều cho phép đưa văn bản UTF-8 trực tiếp vào văn bản:

Lưu trong UTF-8 sẽ đưa ra chuỗi:

00100100 01110011 01110100 01110010 01101001 01101110 01100111 00100000
00111101 00100000 00100010 11100110 10111100 10100010 11100101 10101101
10010111 00100010 00111011

Chỉ 12 byte trong số 17 byte (bắt đầu bằng 1) là ký tự UTF-8 (2 ký tự 3 byte). Các ký tự khác ở dạng ASCII. Trình phân tích cú pháp sẽ đọc như sau:

$string = "11100110 10111100 10100010 11100101 10101101 10010111";

Trình phân tích cú pháp xử lý mọi thứ đằng sau trích dẫn dưới dạng một chuỗi các bit phải được xử lý nguyên trạng, cho đến trích dẫn khác. Nếu bạn chỉ xuất chuỗi này, bạn sẽ xuất văn bản ở dạng UTF-8. Bạn không cần phải làm gì khác. Trình phân tích cú pháp không cần hỗ trợ cụ thể utf-8, nó chỉ cần lấy chuỗi theo nghĩa đen. Các trình phân tích cú pháp đơn giản có thể hỗ trợ Unicode theo cách này mà không thực sự hỗ trợ Unicode. Tuy nhiên, nhiều ngôn ngữ lập trình hỗ trợ rõ ràng Unicode.

Mã hóa và PHP.

PHP không hỗ trợ Unicode. Đúng là anh ấy hỗ trợ nó khá tốt. Đoạn trước cho thấy cách đưa trực tiếp các ký tự UTF-8 vào văn bản chương trình mà không gặp vấn đề gì, vì UTF-8 tương thích ngược với ASCII và đó là tất cả những gì PHP cần. Tuy nhiên, tuyên bố “PHP không hỗ trợ Unicode” là đúng và đã gây ra nhiều nhầm lẫn trong cộng đồng PHP.

Lời hứa sai lầm

Một trong những điều thú vị của tôi là các hàm utf8_encode và utf8_decode. Tôi thường thấy những điều ngu ngốc như "Để sử dụng Unicode trong PHP, bạn cần gọi utf8_encode ở văn bản đầu vào và utf8_decode ở đầu ra." Hai hàm này hứa hẹn một số loại chuyển đổi tự động văn bản UTF-8, được cho là bắt buộc vì “PHP không hỗ trợ Unicode”. Nếu bạn đang đọc bài viết này không theo đường chéo thì bạn biết rằng

  1. Không có gì đặc biệt về UTF-8
  2. Thực tế là bạn không thể mã hóa văn bản thành UTF-8

Hãy để tôi giải thích điểm 2: bất kỳ văn bản nào cũng đã được mã hóa bằng thứ gì đó. Khi bạn chèn dòng vào nguồn, họ đã có mã hóa rồi. Chính xác hơn là mã hóa mà bạn hiện đang sử dụng. soạn thảo văn bản. Nếu bạn lấy chúng từ cơ sở dữ liệu thì chúng đã được mã hóa rồi. Nếu bạn đang đọc chúng từ một tập tin... bạn đã biết rồi phải không?

Văn bản được mã hóa UTF-8 hoặc không được mã hóa. Nếu không, thì nó được mã hóa bằng ASCII, ISO-8859-1, UTF-16 hoặc thứ gì khác. Nếu nó không có trong UTF-8 nhưng được cho là chứa "ký tự UTF-8", thì bạn có sự bất đồng về nhận thức. Nếu văn bản vẫn chứa các ký tự cần thiết được mã hóa bằng UTF-8 thì đó là UTF-8.

Vậy utf8_encode làm cái quái gì vậy?

"Chuyển đổi chuỗi ISO-8859-1 sang mã hóa UTF-8"

Vâng! Tác giả muốn nói rằng hàm chuyển đổi văn bản từ ISO-8859-1 sang UTF-8. Đó là mục đích của nó. Một cái tên khủng khiếp như vậy có lẽ đã được đặt cho nó bởi một người châu Âu ngẫu hứng nào đó. Điều tương tự cũng áp dụng cho utf8_decode. Các chức năng này không thể áp dụng cho bất kỳ mục đích nào khác ngoài việc chuyển đổi từ ISO-8859-1 sang UTF-8. Nếu bạn cần một cặp mã hóa khác, hãy sử dụng iconv.
utf8_encode không dành cho bạn đũa phép, cần phải vẫy tay trên mỗi từ vì “PHP không hỗ trợ Unicode.” Cô ấy gọi nhiều vấn đề hơn, hơn là quyết định - hãy nói lời cảm ơn đến những lập trình viên châu Âu và thiếu hiểu biết đó.

Native-shmativny

Vậy họ có ý gì khi nói một ngôn ngữ hỗ trợ Unicode? Điều quan trọng là liệu ngôn ngữ có giả định rằng một ký tự chiếm một byte hay không. Do đó, PHP cho phép bạn truy cập ký tự đã chọn bằng cách xử lý chuỗi dưới dạng mảng ký tự:

Nếu chuỗi $ có mã hóa một byte thì nó sẽ cung cấp cho chúng ta ký tự đầu tiên. Nhưng chỉ vì “ký tự” giống với “byte” trong mã hóa một byte. PHP chỉ đưa ra byte đầu tiên mà không hề nghĩ đến các ký tự. Chuỗi trong PHP không gì khác hơn là các chuỗi byte, không hơn, không kém. Những “ký tự có thể đọc được” này của bạn không gì khác hơn là một phát minh của con người, PHP không quan tâm đến chúng.

01000100 01101111 01101110 00100111 01110100
Đừng
01100011 01100001 01110010 01100101 00100001
quan tâm!

Điều tương tự cũng áp dụng cho nhiều người tính năng tiêu chuẩn, chẳng hạn như chất nền, strpos, phần cắt và những thứ khác. Hỗ trợ dừng khi ánh xạ byte-ký tự kết thúc:

11100110 10111100 10100010 11100101 10101101 10010111
漢 字

chuỗi $ cho dòng được chỉ định sẽ lại chỉ trả về byte đầu tiên, bằng 11100110. Nói cách khác, byte thứ ba của ký tự 漢. Chuỗi 11100110 không chính xác đối với UTF-8, do đó chuỗi hiện tại cũng không chính xác. Nếu bạn cũng nghĩ như vậy, bạn có thể thử một cách mã hóa khác, trong đó 11100110 sẽ là một ký tự ngẫu nhiên hợp lệ nào đó. Bạn có thể vui chơi, chỉ là không có trên máy chủ chiến đấu.

Đó là tất cả. "PHP không hỗ trợ Unicode" có nghĩa là hầu hết các hàm trong ngôn ngữ đều giả định rằng một byte bằng một ký tự, dẫn đến các ký tự nhiều byte bị cắt bớt hoặc độ dài chuỗi bị tính toán không chính xác. Điều này không có nghĩa là bạn không thể sử dụng Unicode trong PHP hoặc bất kỳ văn bản nào cũng cần được chạy qua utf8_encode hoặc một số nội dung vô nghĩa khác.

May mắn thay, có phần mở rộng đặc biệt, bổ sung tất cả chức năng chuỗi quan trọng nhưng có hỗ trợ mã hóa nhiều byte. mb_substr($string, 0, 1, ‘UTF-8’) trên dòng trên sẽ trả về chính xác chuỗi 11100110 10111100 10100010, tương ứng với ký tự 漢. Bởi vì hàm cần suy nghĩ về những gì nó đang làm nên nó cần phải được mã hóa. Do đó, các hàm này lấy tham số $encoding. Nhân tiện, mã hóa có thể được đặt chung cho tất cả các hàm mb_ ​​bằng cách sử dụng mb_internal_encoding.

Việc sử dụng và lạm dụng xử lý lỗi PHP

Toàn bộ vấn đề với việc hỗ trợ Unicode (không phải) trong PHP là trình thông dịch không quan tâm. Chuỗi byte, ha. Đừng quan tâm chúng có ý nghĩa gì. Không có gì được thực hiện ngoài việc lưu trữ chuỗi trong bộ nhớ. PHP thậm chí còn không có khái niệm như vậy – mã hóa. Và miễn là bạn không cần thao tác với chuỗi thì không vấn đề gì. Công việc được thực hiện với các chuỗi byte có thể được ai đó coi là ký tự. PHP chỉ yêu cầu bạn lưu mã nguồn ở dạng tương thích với ASCII. Trình phân tích cú pháp PHP tìm kiếm các ký tự cụ thể để cho nó biết phải làm gì. 00100100 nói: “khai báo một biến”, 00111101 – “gán”, 00100010 – bắt đầu hoặc kết thúc một dòng, v.v. Mọi thứ không quan trọng đối với trình phân tích cú pháp đều được coi là chuỗi ký tự byte. Điều này cũng áp dụng cho mọi thứ được đặt trong dấu ngoặc kép. Điều này có nghĩa là:

  1. Bạn sẽ không thể lưu nguồn PHP ở dạng mã hóa không tương thích với ASCII. Ví dụ: trong UTF-16, ký tự trích dẫn được mã hóa thành 00000000 00100010. Đối với PHP, coi mọi thứ là ASCII, đây là byte NUL theo sau là một trích dẫn. PHP có thể sẽ gặp trục trặc đối với mọi ký tự và trở thành NUL.
  2. Bạn có thể lưu PHP ở dạng mã hóa tương thích ASCII. Nếu 128 điểm mã hóa đầu tiên khớp với ASCII thì PHP sẽ ăn chúng. Tất cả nhân vật quan trọngđối với PHP nằm trong 128 điểm đầu tiên được xác định bởi ASCII. Nếu chuỗi ký tự chứa bất cứ thứ gì vượt quá giới hạn này, PHP sẽ không chú ý. Bạn có thể lưu nguồn ở định dạng ISO-8859-1, Mac Roman, UTF-8 hoặc bất kỳ mã hóa nào khác. Các ký tự chuỗi trong mã của bạn sẽ nhận được mã hóa mà bạn lưu tệp.
  3. Bất kì tập tin bên ngoàiđối với PHP nó có thể có bất kỳ mã hóa nào. Nếu trình phân tích cú pháp không cần xử lý tệp thì nó sẽ rất vui.
    $foo = file_get_contents("bar.txt");

    Ở trên sẽ chỉ đơn giản là đặt các byte từ bar.txt vào biến $foo. PHP sẽ không cố gắng diễn giải, mã hóa hoặc thao túng nội dung. Tệp có thể chứa dữ liệu nhị phân hoặc hình ảnh, PHP không quan tâm.

  4. Nếu mã hóa bên ngoài và bên trong phải khớp nhau thì chúng thực sự cần như vậy. Một trường hợp phổ biến là bản địa hóa: trong mã bạn viết một cái gì đó như echo localize('Foobar') và trong tệp bên ngoài là:
    msgstr "Foobar"
    msgstr "フーバー"

    Cả hai chuỗi Foobar phải có biểu diễn bit giống hệt nhau. Nếu mã nguồn ở dạng ASCII và mã bản địa hóa ở dạng UTF-16 thì bạn đã không gặp may. Chuyển đổi bổ sung cần phải được thực hiện.

Một người đọc tinh tường có thể hỏi liệu có thể lưu trữ tuần tự một byte UTF-16 thành một chữ không tập tin nguồn bằng ASCII và câu trả lời sẽ luôn là: tất nhiên.

01100101 01100011 01101000 01101111 00100000 00100010
ờ ờ"
11111110 11111111 00000000 01010101 00000000 01010100
(điểm đánh dấu UTF-16) U T
00000000 01000110 00000000 00101101 00000000 00110001
F-1
00000000 00110110 00100010 00111011
6 " ;

Dòng đầu tiên và 2 byte cuối cùng là từ ASCII. Phần còn lại được biểu thị bằng UTF-16, 2 byte cho mỗi ký tự. 11111110 11111111 hàng đầu trên dòng thứ hai là điểm đánh dấu để bắt đầu văn bản trong UTF-16 (bắt buộc theo tiêu chuẩn, PHP chưa bao giờ nghe nói về điều này). Tập lệnh này xuất ra chuỗi “UTF-16” được mã hóa bằng UTF-16 vì nó chỉ xuất ra các byte giữa hai dấu ngoặc kép, dẫn đến văn bản “UTF-16” được mã hóa bằng UTF-16. Mặt khác, nguồn không hoàn toàn chính xác ở dạng ASCII hoặc UTF-16, vì vậy bạn có thể mở một trình soạn thảo và giải trí.

Tổng cộng

PHP hỗ trợ Unicode, hay chính xác hơn là bất kỳ mã hóa nào khá chính xác, miễn là bạn có thể khiến trình phân tích cú pháp thực hiện công việc của nó và nhà phát triển hiểu được nó đang làm gì. Bạn chỉ cần cẩn thận khi làm việc với chuỗi: chia, xóa dấu cách, đếm và tất cả các thao tác khác yêu cầu làm việc với ký tự, không phải byte. Nếu bạn không làm bất cứ điều gì với các chuỗi ngoài đọc và in, bạn sẽ khó gặp phải những vấn đề không tồn tại ở các ngôn ngữ khác.

Ngôn ngữ có hỗ trợ mã hóa

Vậy việc một ngôn ngữ hỗ trợ Unicode có ý nghĩa gì? Ví dụ Javascript hỗ trợ Unicode. Trên thực tế, bất kỳ chuỗi nào trong Javascript đều được mã hóa bằng UTF-8. Và đây là mã hóa duy nhất mà Javascript hoạt động. Bạn sẽ không vào được Chuỗi Javascript không có trong UTF-8. Javascript tôn thờ Unicode đến mức đơn giản là không có công cụ nào trong cốt lõi của ngôn ngữ để hoạt động với các bảng mã khác. Vì Javascript thường chạy nhất trong trình duyệt nên bạn không gặp vấn đề gì: trình duyệt có thể thực hiện logic mã hóa và giải mã I/O tầm thường.

Các ngôn ngữ khác chỉ đơn giản hỗ trợ mã hóa. Công việc nội tâmđược thực hiện bằng một mã hóa duy nhất, thường là UTF-16. Nhưng điều này có nghĩa là họ cần được cho biết văn bản đó đang được mã hóa bằng cách nào, nếu không họ sẽ cố gắng tự xác định nó. Cần phải chỉ ra mã nguồn được lưu bằng mã hóa nào, tệp sẽ đọc sẽ được lưu theo mã hóa nào và đầu ra sẽ được thực hiện bằng mã hóa nào. Ngôn ngữ sẽ thực hiện chuyển đổi nhanh chóng nếu được chỉ định rằng nên sử dụng Unicode. Họ làm mọi thứ mà trong PHP cần phải được thực hiện bán tự động ở đâu đó trong nền. Không tốt hơn hay tệ hơn PHP, chỉ khác biệt thôi. Tin tốt Vấn đề là các hàm chuỗi cuối cùng vẫn hoạt động và bạn không phải lo lắng về việc chuỗi có chứa các ký tự nhiều byte hay không, nên chọn hàm nào để làm việc và những việc khác mà bạn sẽ phải làm trong PHP.

Unicode hoang dã

Vì Unicode giải quyết được rất nhiều nhiều vấn đề khác nhau và hoạt động trong nhiều tình huống khác nhau, bạn phải trả giá bằng cách đào sâu vào vùng hoang dã. Ví dụ: tiêu chuẩn Unicode chứa thông tin về cách giải quyết các vấn đề như thống nhất các chữ tượng hình YAKK. Nhiều biểu tượng phổ biến ở Nhật Bản, Trung Quốc và Hàn Quốc được mô tả hơi khác nhau. Hoặc gặp vấn đề khi chuyển đổi ký tự từ chữ thường lên đầu, ngược lại hoặc qua lại, điều này không phải lúc nào cũng đơn giản như cách mã hóa các ngôn ngữ Tây Âu. Một số biểu tượng có thể được thể hiện bằng các mục khác nhau. Ví dụ: chữ ö có thể được biểu thị bằng mục U+00F6 (“THƯ LATIN NHỎ O CÓ DIARESIS”) hoặc dưới dạng hai mục U+006F (“CHỮ NHỎ O”) VÀ U+0308 (“THAY ĐỔI DIARESIS”) , có nghĩa là chữ o With. Trong UTF-8, nó là 2 byte hoặc 3 byte, trong cả hai trường hợp đều biểu thị một ký tự bình thường. Do đó, có các quy tắc chuẩn hóa trong tiêu chuẩn, tức là làm thế nào để chuyển đổi các hình thức này từ dạng này sang dạng khác. Điều này và nhiều điều khác nằm ngoài phạm vi của bài viết này, nhưng bạn cần biết về những điểm này.

Tôi không ép nó nữa!
  1. Văn bản luôn là một chuỗi các bit cần được dịch sang ngôn ngữ tự nhiên bằng cách sử dụng bảng. Bảng không hợp lệ - biểu tượng không hợp lệ.
  2. Bạn không thể làm việc trực tiếp với văn bản - bạn luôn phải làm việc với các phần được gói gọn trong các phần trừu tượng. Các lỗi là do lỗi ở một trong những phần tóm tắt.
  3. Các hệ thống truyền thông tin cho nhau phải luôn chỉ ra mã hóa đang hoạt động. Ví dụ: trang web cho trình duyệt biết rằng nó cung cấp thông tin ở dạng UTF-8.
  4. Ngày nay, UTF-8 tương thích ngược với ASCII, mặc dù thực tế là nó có thể mã hóa hầu hết mọi ký tự và vẫn tương đối hiệu quả trong hầu hết các trường hợp. Các bảng mã khác cũng có công dụng của chúng, nhưng phải có lý do chính đáng để bận tâm với các bảng mã chỉ hỗ trợ một phần Unicode.
  5. Cả chương trình và người lập trình đều phải giải quyết vấn đề khớp byte và ký tự.

Bây giờ bạn không cần phải bào chữa khi làm lộn xộn văn bản nữa.

Thẻ: Thêm thẻ

Nếu mã hóa không chính xác, toàn bộ hoặc một phần trang web sẽ được hiển thị dưới dạng “kryapozyablov”, tức là. nhân vật lạ, làm cho văn bản không thể đọc được. Tình trạng này có thể xảy ra khi cài đặt không chính xác mã hóa máy chủ web hoặc nếu không có cài đặt. Hãy xem xét những lựa chọn khả thi và cách giải quyết vấn đề

Mã hóa trang HTML không chính xác

Hãy tạo một tệp thử nghiệm:

Sudo gedit /var/www/html/encoding.html

Hãy sao chép vào nó:

Kiểm tra mã hóa

Hãy mở tập tin này trong trình duyệt

Như bạn có thể thấy, mã hóa bị trình duyệt phát hiện không chính xác:

Có một số cách để khắc phục tình trạng này. Hãy bắt đầu với điều đơn giản nhất - chỉ định rõ ràng cách mã hóa cho trang web. Việc này được thực hiện bằng thẻ meta, thẻ này phải nằm bên trong thẻ cái đầu:

Hãy thêm dòng này vào tệp thử nghiệm của chúng tôi để nó trông như thế này:

Kiểm tra mã hóa

Tệp thử nghiệm để kiểm tra mã hóa

Như chúng ta có thể thấy trong ảnh chụp màn hình sau, vấn đề đã được giải quyết:

Nếu mã hóa tập tin của bạn khác với UTF-8, sau đó thay thế nó bằng windows-1251 hoặc một mã phù hợp với mã hóa của trang web. Để tìm hiểu cách phát hiện mã hóa tệp, hãy xem.

Đây là cách dễ nhất để khắc phục sự cố mã hóa - mà không cần thay đổi cài đặt máy chủ.

Hãy trả lại tập tin thử nghiệm của chúng tôi cho trạng thái ban đầu và tiếp tục nghiên cứu cách xác định mã hóa.

Nếu tập tin .htaccess bao gồm cài đặt Apache, thì những tệp này có thể được sử dụng để chỉ định mã hóa các trang được gửi bởi máy chủ web. Để kích hoạt hỗ trợ tập tin .htaccess V. tập tin cấu hình Apache ( /etc/apache2/apache2.conf) tìm một nhóm dòng

Tùy chọn Chỉ mục FollowSymLinks AllowOverride Không Yêu cầu tất cả được cấp

Và thay thế nó

AllowOverride Không có

Cho phépGhi đè tất cả

Sau này, máy chủ cần phải được khởi động lại.

Sudo systemctl khởi động lại Apache2.service

Tài liệu .htaccess phải được đặt trong cùng thư mục với trang web. Trang web của tôi được lưu trữ trong thư mục gốc của máy chủ web. Nếu bạn có cái tương tự thì bây giờ trong thư mục /var/www/html/ tạo một tập tin .htaccess và thêm lệnh vào nó Thêm bộ ký tự mặc định sau đó cho biết mã hóa mong muốn. Ví dụ

AddDefaultCharset UTF-8

AddDefaultCharset windows-1251

Bạn có thể chỉ định mã hóa sẽ chỉ được áp dụng cho các tệp có định dạng nhất định:

AddCharset utf-8 .atom .css .js .json .rss .vtt .xml

Tập hợp các tệp có thể là bất cứ thứ gì, ví dụ:

AddCharset utf-8 .html .css .php .txt .js

Tùy chọn sau đây là một lựa chọn thay thế và cũng cho phép bạn đặt mã hóa cho các tệp loại nhất định, nó cần được bật mod_headers:

Bộ tiêu đề Loại nội dung "text/html; charset=utf-8"

Một tùy chọn khác cũng có thể được sử dụng trong tệp .htaccessđể đặt mã hóa UTF-8:

Tùy chọn chỉ mục + Bộ ký tự=UTF-8

Nếu trang web bằng PHP thì bạn có thể cần phải sao chép mã hóa bằng php_value default_charset:

AddDefaultCharset windows-1251 php_value default_charset "cp1251"

Thay vì tạo tệp .htaccess, bạn có thể đặt mã hóa trong tệp cấu hình máy chủ web. Đối với Apache CentOS/Fedora đây là tệp httpd.conf và trên Debian/Ubuntu đây là tệp apache2.conf. Thêm vào hàng tiếp theođể đặt mã hóa và khởi động lại máy chủ web để các thay đổi có hiệu lực:

AddDefaultCharset UTF-8

Cách đặt mã hóa UTF-8 trong PHP

TRONG Tập lệnh PHP Nó được sử dụng để thiết lập mã hóa tiêu đề, Ví dụ:

Header("Content-Type: charset=utf-8");

Thông thường, cùng với mã hóa, loại nội dung cũng được chỉ định (trong ví dụ này là tùy chọn cho trang HTML):

Header("Content-Type: text/html; charset=utf-8");

Một tùy chọn khác cho nguồn cấp dữ liệu RSS:

Header("Loại nội dung: text/xml; charset=utf-8");

Hãy nhớ rằng chức năng tiêu đề phải được gọi trước khi xuất bất kỳ thông tin nào ra trình duyệt. Mặt khác (nếu đầu ra tới trình duyệt đã được tạo) thì các tiêu đề đã được gửi. Rõ ràng, trong trường hợp này không thể thay đổi chúng được nữa. Nếu một thông báo lỗi được xuất ra trình duyệt thì có nghĩa là các tiêu đề đã được gửi và việc sử dụng tiêu đề sẽ gây ra lỗi. Để kiểm tra xem tiêu đề đã được gửi chưa, hãy sử dụng tiêu đề_đã gửi.

Phương pháp được mô tả chỉ hoạt động khi tập lệnh PHP tạo ra hoàn toàn nội dung của trang. Bạn nên lưu các trang tĩnh (chẳng hạn như html) ở dạng mã hóa utf-8. Hầu hết các máy chủ web sẽ lưu ý đến mã hóa của tệp và thêm tiêu đề tương ứng. Trên thực tế, tiết kiệm tập tin PHP trong mã hóa utf-8 sẽ dẫn đến kết quả tương tự.

Mã hóa kết quả không chính xác từ cơ sở dữ liệu MySQL

Nếu trang web của bạn bao gồm phần tĩnh (mẫu) và phần động, được hình thành từ dữ liệu nhận được từ cơ sở dữ liệu, thì tình huống có thể phát sinh khi một phần của trang web có mã hóa chính xác và phần khác của trang web có mã hóa sai. một. Trong trường hợp này, việc thay đổi cài đặt máy chủ web là vô ích - vì vẫn như vậy, một phần của trang sẽ có mã hóa sai.

Bạn cần bắt đầu bằng cách xác định mã hóa các bảng của mình. Bạn có thể nhìn vào phpMyAdmin:

Hãy chú ý đến cột " So sánh", lối vào " utf8_unicode_ci" có nghĩa là mã hóa được sử dụng UTF-8.

Bạn có thể kết nối với Cơ sở dữ liệu MySQL và kiểm tra mã hóa các bảng không có phpMyAdmin. Đối với điều này:

Mysql -u gốc -p

Nếu bạn quên tên cơ sở dữ liệu, hãy chạy lệnh:

HIỂN THỊ CƠ SỞ DỮ LIỆU;

Giả sử tôi muốn tra cứu mã hóa cho các bảng trong cơ sở dữ liệu information_schema

SỬ DỤNG thông tin_lược đồ;

Nếu bạn quên tên các bảng, hãy chạy:

HIỂN THỊ CÁC CỘT ĐẦY ĐỦ TỪ table_name;

Ví dụ:

HIỂN THỊ CÁC CỘT ĐẦY ĐỦ TỪ GLOBAL_STATUS;

Bạn sẽ thấy một cái gì đó như thế này:

Xem cột đối chiếu. Trong trường hợp của tôi có utf8_general_ci, nó giống như utf8_unicode_ci, mã hóa UTF-8. Nhân tiện, nếu bạn không biết sự khác biệt giữa các bảng mã là gì utf8_general_ci, utf8_unicode_ci, utf8mb4_general_ci, utf8mb4_unicode_ci và cũng nên chọn mã hóa nào cho cơ sở dữ liệu MySQL, sau đó hãy xem.

Bây giờ chúng ta đã biết mã hóa (trong trường hợp của tôi là UTF-8), mỗi khi bạn kết nối với MySQL DBMS, bạn cần thực hiện các truy vấn một cách tuần tự:

ĐẶT TÊN UTF8 THIẾT LẬP CHARACTER SET UTF8 SET character_set_client = UTF8 SET character_set_connection = UTF8 SET character_set_results = UTF8

Trong PHP điều này có thể được thực hiện như thế này:

$this->mysqli = new mysqli($server, $username, $password, $basename); if ($this->mysqli->connect_error) ( $this->errorHandler_c->logError(1, "Lỗi kết nối (" . $this->mysqli->connect_errno . ") " . $this->mysqli->connect_error , $_SERVER ["REQUEST_URI"] ) $this->mysqli->query("SET TÊN UTF8"); $this->mysqli->query("SET CHARACTER SET UTF8"); $this->mysqli->query("SET character_set_client = UTF8"); $this->mysqli->query("SET character_set_connection = UTF8"); $this->mysqli->query("SET character_set_results = UTF8");

lưu ý rằng UTF8 bạn cần thay thế nó bằng mã hóa được sử dụng cho các bảng của bạn.

Thay đổi mã hóa tập tin

Nếu bạn quyết định đi theo con đường khác và thay vì cài đặt một mã hóa mới, hãy thay đổi mã hóa các tệp của bạn, thì hãy xem bài viết “”. Nó cho bạn biết cách tìm ra mã hóa hiện tại của tệp và cách chuyển đổi tệp sang bất kỳ mã hóa nào (không chỉ UTF-8).

Làm cách nào để biết máy chủ đang gửi mã hóa gì

Nếu bạn muốn tìm hiểu xem máy chủ web có cài đặt mã hóa nào (mã hóa nào nó gửi trong tiêu đề), hãy sử dụng lệnh sau:

URL cuộn tròn -s -o /dev/null -D /dev/stdout | grep -E "bộ ký tự"

Trong đó thay vào đó URL chèn địa chỉ thực trang web đang được kiểm tra. Ví dụ: nếu trang web sử dụng HTTPS, hãy chỉ định địa chỉ trang web cùng với giao thức

Curl https://softocracy.ru -s -o /dev/null -D /dev/stdout | grep -E "bộ ký tự"

Chọn mã hóa nào cho trang web

Ngày nay việc mã hóa ASCII là tiêu chuẩn để biểu diễn 128 ký tự đầu tiên (bao gồm số và dấu câu) của bảng chữ cái tiếng Anh, được trình bày theo một thứ tự cụ thể.

Tuy nhiên, ngay cả 1 byte cũng cho phép bạn mã hóa giá trị gấp 2 lần, nghĩa là không phải 128 mà lên tới 256 những nghĩa khác nhau. Vì vậy, đủ nhanh để thay thế cơ bản ASCII Các phiên bản mở rộng hơn của bảng mã nổi tiếng và phổ biến này bắt đầu xuất hiện, trong đó các ký tự của bảng chữ cái và theo đó, văn bản của nhiều ngôn ngữ khác nhau, bao gồm cả tiếng Nga, cũng được mã hóa.

Phần mở rộng ASCII cho Nga

Hôm nay cho Người dùng Ngaưu tiên là mã hóa Windows1251 và mã hóa Unicode nữa UTF 8 bắt nguồn từ ASCII.

Trên thực tế, ai đó có thể có một câu hỏi rất công bằng: "Tại sao lại cần những mã hóa văn bản này?"
Điều cần nhớ là máy tính chỉ là một cỗ máy phải hoạt động đúng theo hướng dẫn. Để làm rõ những gì cần phải làm với mỗi ký tự được viết, nó được biểu diễn dưới dạng một tập hợp các dạng vectơ, mỗi bộ được gửi đến Đúng vị tríđể một hoặc một chỉ định khác xuất hiện trên màn hình.

Phông chữ chịu trách nhiệm hình thành các dạng vectơ và bản thân quá trình mã hóa phụ thuộc vào hệ điều hành, cũng như các chương trình được sử dụng trong đó. Do đó, về bản chất, mỗi văn bản là một tập hợp byte nhất định, mỗi byte đại diện cho mã hóa của một ký tự viết. Và chương trình hiển thị thông tin được in trên màn hình (đây có thể là trình duyệt hoặc trình xử lý văn bản) phân tích mã, tìm màn hình phù hợp theo mã của nó trong bảng mã hóa, chuyển đổi nó thành dạng vectơ cần thiết và hiển thị nó trong văn bản tài liệu.

Mã hóa CP866 và KOI8-Rđã được sử dụng rộng rãi trước khi hệ điều hành đồ họa ra đời, hệ điều hành này đã trở nên phổ biến trên toàn thế giới - các cửa sổ. Bây giờ mã hóa phổ biến nhất hỗ trợ tiếng Nga là Windows1251.

Tuy nhiên, nó không phải là duy nhất, vì vậy các nhà sản xuất phông chữ tiếng Nga được sử dụng trong phần mềm Thỉnh thoảng, thậm chí cho đến ngày nay, những khó khăn vẫn nảy sinh liên quan đến việc hiển thị không chính xác các ký hiệu và sự xuất hiện của cái gọi là krakozyabry. Những chữ tượng hình vụng về này là kết quả sử dụng không đúng cách các bảng mã hóa, nghĩa là các bảng khác nhau đã được sử dụng trong quá trình mã hóa và giải mã.

Tình trạng tương tự cũng xảy ra trên các trang web, blog và các nguồn khác có thông tin bằng tiếng Nga và các ký tự nước ngoài khác ngoài tiếng Anh. Tình huống này xác định điều kiện tiên quyết chính để tạo ra một mã hóa phổ quát cho phép bạn mã hóa văn bản bằng bất kỳ ngôn ngữ nào, kể cả tiếng Trung, nơi có nhiều ký tự hơn 256.

Mã hóa phổ quát

Phiên bản đầu tiên của mã hóa phổ quát được phát triển trong tập đoàn Unicode là mã hóa UTF 32. 32 bit được sử dụng để mã hóa từng ký tự. Mã hóa hiện đã được thực hiện lượng lớn dấu hiệu, nhưng một vấn đề khác lại xuất hiện - đối với phần lớn các nước châu Âu một con số như vậy ký tự phụ nó hoàn toàn không cần thiết. Rốt cuộc, tài liệu hóa ra rất nặng. Vì vậy, để thay thế UTF 32đã đến UTF 16, đã trở thành cơ sở cho tất cả các biểu tượng được sử dụng ở nước ta và hơn thế nữa.

Nhưng vẫn có khá nhiều người không hài lòng. Ví dụ, những người chỉ giao tiếp bằng tiếng anh, kể từ khi chuyển từ ASCII sang UTF 16 tài liệu của họ vẫn tăng kích thước và đáng kể, gần gấp 2 lần.
Kết quả là mã hóa có độ dài thay đổi UTF 8, điều này giúp không thể tăng trọng lượng của văn bản.

Krakozyabry và phương pháp đối phó với chúng

Nói chung, mã hóa được đặt trên trang nơi Thông báo. Kết quả là, ở phần đầu của tài liệu, một loại dấu hiệu được hình thành để ghi nhớ nó, trực tiếp hoặc trực tiếp. thứ tự ngược lại mã ký tự được viết UTF16.

Nếu một cái gì đó được in trong UTF-8, thì không có điểm đánh dấu ở đầu, vì không có khả năng viết mã ký tự theo thứ tự ngược lại trong bảng mã này.

Vì vậy, bạn nên lưu mọi thứ đã gõ vào trình soạn thảo, không có dấu ( BOM) để giảm khả năng xuất hiện lỗi vô nghĩa trong tài liệu.

Một mẹo hữu ích khác để chống lại krakozyabrs là viết vào tiêu đề mã của mỗi trang trên trang web thông tin về mã hóa văn bản chính xác để không localhost, cũng không có sự nhầm lẫn nào trên máy chủ.

Ví dụ như thế này