Chinese (Traditional) (中文(繁體)) translation by tianyiliang (you can also view the original English article)

編碼只是那些必須要做對的事情之一. 如果編碼錯了, 那什麼也運行不起來. 如果做對了也不會引起任何人注意. 這使得編碼處理令人討厭。
儘管如此,幸運的是大部分的要做的事都已經準備好了.。 我們只需要確保我們的檔是保存 (和傳輸) 的是正確的編碼。 正確的編碼是我們指定的。 它可以是任何東西,只要它包含我們需要的所有的字元和我們想要保持一致的長度。
有三個重要文本 HTML 編碼規則:
- 使用正確的編碼載入內容。
- 使用相同的編碼傳輸。
- 確保用戶端使用相同編碼讀取內容。
在這篇文章中,我們會深入學習這三個規則的詳細內容, 特別是第二和第三個規則. 最後我們將也看看形式編碼,這與文本編碼沒有直接關係,但是有間接關係。 我們將會知道他們為什麼會有一些聯繫。
選擇正確的編碼
除非我們知道我們的內容應放在一些國家特定的編碼否則我們應該只使用UTF-8。 有很多理由讓我們只選擇utf-8。 它不是在記憶體中存儲的最好形式,但它是是作為資料交換和內容傳輸的基本形式。 不用想就是用它就對。 不過,一個通常的錯誤是utf-8不適合保存檔. 在文本沒有編碼前,我們應該謹慎的選擇編碼.
Sublime Text用戶和許多其它文字編輯器使用者也許從來不會遇到錯誤編碼的問題. 因為這些編輯器缺省使用UTF-8保存. 有的編輯器,主要是為 Windows 平臺上,使用不同的默認格式,例如,Windows 1252。
即使在Sublime Text,它有很多標準的操作是用來更改檔的編碼的。 在我們選擇File功能表中使用Save with Encoding來把檔保存為我們想要的編碼格式.。 僅此而已!

原則上每個更高級的編輯器都應該有這樣的選項。 有時他們會有一個高級保存按鈕.。 例如,微軟的 Visual studio 編輯器按一下檔功能表中的高級保存選項能彈出一個指定的對話方塊。

我們應該確保使用正確的編碼。 這將為我們的內容和使用的位元組數一致。 UTF-8 的主要優點是只需要單個位元組,如果我們不使用特殊字元的話。 每個字元最多消耗4個位元組。 這是動態的而且UTF-8是文本存儲和傳輸的理想格式。 然而,警告是 UTF-8 不是字串存在記憶體中的最佳格式。
控制傳輸
HTTP 協定傳輸資料以純文字格式。 即使我們決定對內容進行編碼傳輸 GZip 或如果我們使用 HTTPS,加密的內容,作為底層內容仍是只是純文字。 我們已經學到過這不僅僅是純文字.。 我們總是需要將內容與一些編碼得到的文本表示形式相關聯。
一條 HTTP 消息被拆分成兩個部分。 上半部分稱為標頭。 由一個空行分隔是下半的部分: 身體。
總有至少兩個 HTTP 消息: 請求和其相關聯的回應。 這兩種類型的消息分享這種結構。 響應的正文是我們想要傳輸的內容。 請求的正文只是感興趣的表單提交,我們稍後就會介紹。 如果我們想要提供一些資訊編碼的內容,我們必須提供一些標頭中的資訊。
在以下的header告訴接收方正文內容是被稱為HTML的指定文本格式,使用 UTF-8 字元集。
Content-Type: text/html; charset=utf-8
也是content-Encoding
頭內容。 我們總是很容易混淆的內容編碼與內容的實際文本編碼。 前者用來指定的整個包,例如 GZip 編碼,而後者用作初始設置,例如,解析提供的內容。
如果我們關心這一步的正確性我們必須確保我們的 web 伺服器發送正確的報頭。 大多數 web 框架提供這種能力。 在 PHP 中,我們可以這樣編寫:
header('Content-Type:text/html; charset=utf-8');
在 Node.js 我們可能想要使用以下,在 res
是表示請求的變數:
res.setHeader('Content-Type', 'text/html; charset=utf-8');
通過的傳播的報頭的內容可以來決定得HTML文本掃描器的輸入設置. 在前面的例子中,我們使用 utf-8。 等下: 那麼初始設定呢! 有許多方法可以重寫此設置。 如果實際的內容不是 utf-8,掃描器可能認識到這一點,並更改的設置。 由位元組順序標記 (稱為 BOM) 檢測或在內容中查找特定編碼的模式,可能會觸發這種變化。 與此相反的是,前者看起來認為添加上的.
最後,編碼可能會改變我們的 HTML 代碼。 而且只能改變一次.
固定的編碼
當DOM 構造函數處理meta
標記時,它會尋找 charset
的定義.。 只要找到一個,就從中提取字元集。 如果能成功提取並且提取的編碼是有效,我們就將提取出的編碼設置為掃描字元的新編碼。 在這之後編碼將被凍結,並且再也不能更改。
這裡有一點要注意. 為了檢查是否之前的掃描已經完成,我們需要比較已經掃描的字元集和將要掃描的字元集. 因此,我們需要看到是否提前改變編碼會發生一些變化.. 如果我們發現變化,我們需要重新開機整個解析過程。 否則整個DOM結構可能從這個節點往後開始出錯。
從這裡我們已經學會了兩點:
- 使用
< meta charset = utf-8 >
(或一些其他編碼)是必不可少的 。 - 只有在 HTML 中指定的
charset
屬性之前只能使用 ASCII 字元集。
最後,良好的html模版開始應該像下面一樣。 像我們之前學過的文章一樣,我們省略了head
和body
以及後面的標記。 這段代碼做了兩件正確的事情, 它定義了正確的文檔類型, 並且設置了文檔的字元集.
<!DOCTYPE html> <html lang="en"> <meta charset="utf-8"> <title>Title here</title> <!-- ... -->
唯一剩下的問題是: 如果我忘記了這三個步驟之一,會發生什麼? 好吧,第一和第三個步驟是最重要的。 傳輸實際上沒有那麼糟糕。 如果在HTTP的頭部沒有給定初始編碼,流覽器將選擇基於使用者的區域設置的初始編碼。 在德國的區域設置中,我們得到 Windows 1252。 這是實際是大多數國家的默認設置。 一些國家,如波蘭和匈牙利,選擇 Latin2,也被稱為 iso 8859-2編碼。
如果按照之前我們的練習去做,原則上我們不需要擔心這個初始的編碼. ASCII 是一個子集的 Unicode,大多數在使用的編碼,實際上只是 ASCII 的擴展來滿足一個或多個國家的具體需要。 在使用一個指定的字元集錢如果我們只使用基本的 ASCII 字元,應該沒問任何問題。
大多數的錯誤是在像用戶端發送資料,存儲/讀取或生成 meta
標籤的語句時發生衝突. 如果出了錯我們可能會看到類似於下面的效果圖。 這不是一個令人愉快的用戶體驗。

還是重新選擇正確的編碼,這就是為什麼 UTF-8 是最好的選擇的原因。 加上其它編碼足夠我們顯示的需要了. 然而,如果我們提供表單輸入的欄位,我們可能會有麻煩。 在這一點上我們不控制任何更多地使用的字元。 允許使用者輸入任何內容在這裡。 讓我們看看我們如何能控制表單輸入的編碼。
提交表單
如果表單提交一些確定的編碼類型,和伺服器回應的類型不一致,例如 GZip 編碼類型相同。 表單的編碼類型決定表單發送到伺服器之前的序列化。 這種方法與HTTP verb結合在一起非常有用.
原始表單提交使用 POST
作為 HTTP 方法,但是 GET
,PUT
和DELETE
也很常見。 並且只有POST
和PUT
方法支援body內容傳輸請求. 流覽器根據元素的 enctype屬性來指定的編碼類型來構建內容. 通過在 HTTP 請求中設置的Content-Type-header
來傳輸編碼類型。
有三個既定的編碼類型:
- URL 編碼 (預設值,顯式 application/x-www-form-urlencoded)
- 純文字編碼類型 (text/plain)
- 混合編碼類型(multipart/form-data)
第一種和第二種是很相似的但他們還是有細微 (並且非常重要的) 差異。 第三個種方法是最強大的方法。 它甚至允許運送任意檔作為附件。
前兩種類型之間的關鍵區別是,URL編碼形式對表單所有名稱和值進行百分比編碼,而純文編碼傳輸做不到。 百分比編碼保證接收方可以區分名稱和值。 這種提交方式是純文字表單提交做不到的. 第三個不一樣的地方是構建每個實例時使用了邊界字串分割每個實例.
讓我們通過提交一個簡單表單看看差異在哪裡。 表單包含下列代碼:
<input name="first" value="With spaces+signs"> <input name="second" value="Hällo Dü?"> <textarea name="third"> Multi lines rock</textarea>
提交表單,而無需指定任何編碼類型傳輸下列內容:
first=With+spaces%2Bsigns&second=H%E4llo+D%FC%3F&third=Multi%0D%0Alines%0D%0Arock
URL編碼將空格轉換為加號。 原來的加號,像所有的"特殊"字元,按百分比編碼規則轉換。 這尤其適用於換行,原來的 \r\n
,現在顯示為 %0D%0A
。
讓我們看看純文字編碼輸出後看起來像的樣子。
first=With spaces+signs second=Hällo Dü? third=Multi lines rock
用換行來分割的一對對文本. 如果遇到內容中包含多行,可能會導致不正確的描述。
混合編碼的優點是結合了純文字提交的方式並且定義了分割字串,基本上解決了純文字編碼的問題。 唯一的缺點是增加內容長度。
------WebKitFormBoundaryzQRASBvDO1bUB5Lp Content-Disposition: form-data; name="first" With spaces+signs ------WebKitFormBoundaryzQRASBvDO1bUB5Lp Content-Disposition: form-data; name="second" Hällo Dü? ------WebKitFormBoundaryzQRASBvDO1bUB5Lp Content-Disposition: form-data; name="third" Multi lines rock ------WebKitFormBoundaryzQRASBvDO1bUB5Lp--
最後兩個表單編碼方法對我們輸入的特殊字元不做任何轉換。 表單傳輸方法主要靠相應的 <form>
元素 accept-charset
屬性的設置。 如果沒有這樣的屬性,使用頁面的編碼設置。 再次強調,設置了正確的編碼是重要的。
將來我們將會看到第四個編碼類型,稱為application/json
。 顧名思義,它會將表單內容打包為一個JSON字串。
結論
選擇正確的編碼,可以簡單只選取UTF-8。 使用相同的編碼類型可以避免大部分的錯誤. 在運輸過程中的定義編碼是非常有用的,雖然在HTML中帶有charset
屬性的<meta>
元素不是必須要求的,但是這卻是一種確定編碼方式非常好的方法。
表單提交是一個過程,依賴於選擇正確的編碼 — — 不僅為文本,提交編碼本身。 在一般情況下我們可以總是選擇multipart/form-data
作為 enctype
,即使預設的編碼類型可能更好 (較小) 的情況下。 在生產環境中我們永遠不應該使用text/plain
。
參考資料
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post