编程与软件工程joelonsoftware.com编辑精选
每个软件开发者绝对必须知道的 Unicode 知识
The Absolute Minimum Every Software Developer Must Know About Unicode
2010 — 2014,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
Joel Spolsky 2003 年的经典文章,讲解每位软件开发者都应了解的 Unicode 基础知识:字符集与编码的区别、UTF-8 和 UTF-16 的工作原理,以及日常开发中为什么会出现乱码。文章写作时 Windows 是主流平台,但核心概念至今仍然适用。
为什么经久不衰:它用通俗幽默的方式把 Unicode 的核心概念讲清楚了,近二十年来一直是开发者的入门必读,反复被推荐给新手和忘记旧知识的老手。
HN 评论精选
给出五条实用建议:外部文本用 UTF-8、显式声明编码、清楚字符串类型、注意解码边界、复用测试良好的代码。
几点我希望告诉所有新手以避免 Unicode 麻烦的事:尽可能对外部文本使用 UTF-8——如果合作者有别的想法,用好吃的饼干贿赂他们,因为这个选择能省去大量麻烦;明确声明你在用 UTF-8,比如网页要在 HTTP 头里设好 charset=utf-8;在编程语言里处理字符串时,始终清楚它是 Unicode 码点数组、UTF-8 字节数组,还是第三种乱七八糟的东西;注意跨越码点与外部编码的边界,解码可能失败,最好尽早拒绝无效文本;有疑问时使用别人写好的 Unicode 处理代码——野外的疯狂问题大多已有经过测试的处理代码。
pjscott查看英文原文
A few things I wish I could tell all newbies about staying out of trouble with Unicode: * Use UTF-8 for external text, whenever possible. If your collaborators have other ideas, bribe them with tasty cookies or something, because this right here solves a lot of hassles. There are some circumstances in which a different encoding might have its advantages, but it is tremendously reassuring to be able to say "Ah, text! I shall decode it as UTF-8!" and be right. This has the advantage of being compatible with ASCII input, and avoiding the perennial UTF16/UCS2 confusion. * Make it explicit that you're using UTF-8. For example, if you're making a web page, be sure to set "Content-Type: text/html; charset=utf-8" in the HTTP headers, to make the browser's content encoding detection trivially correct. * When dealing with strings in your favorite programming language, always know whether it's an array of Unicode code-points, or of bytes in UTF-8, or some third messed-up thing. Not all strings are the same kind of thing! Unless your programming language has this distinction enforced by its type system, of course. * Be aware when you're crossing the boundary between Unicode code points and Unicode in some external encoding. Decoding can fail, so be prepared. It's best to reject invalid text as early as possible. * When in doubt, use other people's code for Unicode handling. For most of the crazy crap you run into in the wild, there is well-tested crazy-crap-handling code.
补充强调 UTF-8 的全面优势,并纠正文章中 UTF-16 与 UCS-2 的混淆。
这篇文章主要讲 Windows 且写于 2003 年,因此没有充分强调当前的标准做法:尽可能处处使用 UTF-8。UTF-8 向后兼容、被误读时结果相对合理、空间效率高、避免字节序问题,是大多数 Mac 和 Linux C API 的事实编码,而且可以高精度验证。如果你必须选一种编码,总是尽量用 UTF-8;Win32 API 是唯一常用的、经常需要非 UTF-8 的 API(Windows Unicode API 用 UTF-16,不是文章所说的 UCS-2),但文本文件仍应使用 UTF-8。
gilgoomesh查看英文原文
This article deals mostly with Windows and is from 2003 so it fails to emphasise the current standard practice as much as it should: Use UTF-8 everywhere you can. UTF-8 is: * the most backwards compatible (can be passed through many tools intended for ASCII-only with a few limitations – including avoiding composed latin glyphs) * most likely to give an appropriate result if the end-user incorrectly interprets it * the most space efficient encoding (on average) * avoids endianness problems * de-facto encoding for most Mac and Linux C APIs * verifiable with a high degree of accuracy (unlike many other encodings which can't be verified at all) Specifically: * If you have to pick an encoding, always try to use UTF-8 unless you're only storing text to pass into an API which requires something different. * The Winapi (aka Win32) is the only commonly used API that regularly requires something other than UTF-8 (the Windows Unicode APIs use UTF-16 – not UCS-2 as indicated in the Spolsky article). Windows' UTF-16 requirement a pain for platform independence -- be careful. However, you should still aim to use UTF-8 for all text files on Windows and only use UTF-16 for the Windows API calls (never use the locale specific non-Unicode encodings). * There are a few language+environment combinations that literally can't open Unicode filenames. These include MinGW C++ which has no platform independent way of opening file streams with unicode filenames. You need to fall back to C _wfopen and UTF-16 to open files correctly. Note: you don't always have to choose the encoding. e.g. the Mac class NSString or the C# String class use UTF-16 internally, you don't normally need to care what they do internally since any time you access the internal characters, you specify the desired encoding. You should usually extract characters in UTF-8.
指出 UTF-16 辅助平面字符占 32 位,以及 JavaScript 的 UCS-2 语义导致双宽字符 length 和切片问题。
总结得不错,但有一个重要细节:UTF-16 中一些位于辅助平面(不在基本多文种平面)的码点占用 32 位,例如 Emoji。UCS-2 是严格的 16 位编码(UTF-16 的子集),无法表示所有字符;JavaScript 用的就是 UCS-2,所以遇到双宽字符时会有问题——`"🐙🐚🐛🐜🐝🐞🐟".length` 得到 14,尽管只有七个字符,而且你可能会在字符中间切割字符串。
pygy_查看英文原文
A good summary, but for one imortant detail: In UTF-16, some code points (laying on the so-called "astral planes", ie not on the "basic multilingual plane") take 32 bits. The Emoji, for example, lie on the first higher plane: 🍒🎄🐰🚴. Firefox and Safari display them properly, Chrome doesn't, no idea for IE and Opera. UCS-2 is a strict 16-bit encoding (a subset of UTF-16), and it cannot represent all characters. It is the encoding used by JavaScript, which can be problematic when double width characters are used. For example, `"🐙🐚🐛🐜🐝🐞🐟".length` is 14 even though there are only seven characters, and you could slice that string in the middle of a character.
用亲身经历反驳文章中“EBCDIC 无关紧要”的说法,指出遗留系统仍在现实中存在。
文章说“EBCDIC 与你的生活无关,我们不必追溯那么久远”,我希望这是真的。对 99% 的人来说可能是,但野外仍有大量 EBCDIC 和古老的 COBOL 系统需要与现实世界交互。我负责的一块电信软件就要与 EBCDIC 系统接口,需要做基本的到 UTF-16 的转换,再传回去。不算太难,直到你遇到各种数字编码,没人能决定用 BCD、Pic9s、纯 int 还是哪种字节序。EBCDIC 在 2003 年没消亡,2012 年也肯定没有。
cydonian_monk查看英文原文
"EBCDIC is not relevant to your life. We don't have to go that far back in time." I wish this was the case. And for 99% of you it might be. But there's still lots of EBCDIC (and antique COBOL) out in the wild that increasingly has to interact with the real world. One of the chunks of telephony software I'm responsible for has to interface with an EBCDIC system, requiring some basic translation to UTF-16. (And then eventually has to pass some of this now UTF data back to the EBCDIC system.) Not exactly difficult until you get to the various numeric encodings and no one can decide if they want Binary-Coded Decimal, Pic9s, pure int, signs, which endianess (if they even know about endianess), et cetera. EBCDIC wasn't dead in 2003 when Joel wrote this and it certainly (and unfortunately) isn't dead in 2012.
历次讨论
同类还值得读
开源应用架构
The Architecture of Open Source Applications
《开源软件架构》(AOSA)是一本在线免费书,邀请知名开源项目的作者亲自剖析其内部设计,涵盖 SQLAlchemy、LLVM、Audacity、Apache、Bash 等系统。
编程与软件工程上首页 9 次 · 2011–2024aosabook.org编辑精选编程语言简史:简短、不完整且多半错误
A Brief, Incomplete, and Mostly Wrong History of Programming Languages
一篇以戏谑、故意不准确的方式回顾编程语言史的博客文章,用夸张轶事和讽刺定义串起 Lisp、C、C++、Java、JavaScript、PHP 等语言。
编程与软件工程上首页 8 次 · 2009–2021james-iry.blogspot.comSQLite 是如何测试的
How SQLite is tested
SQLite 官方文档页,系统介绍 SQLite 的测试体系:多种测试方法(TCL 测试、模糊测试、回归测试、静态分析等)和海量测试用例,展示了这个小型开源项目如何靠极致测试获得…
编程与软件工程上首页 8 次 · 2009–2025sqlite.org编辑精选高级编程语言(2009)
Advanced programming languages (2009)
Matt Might 的经典文章,按用途推荐“高级编程语言”:如果追求就业就选主流语言,如果追求表达力、学术研究或创业,则推荐 Haskell、OCaml、Scala 等函数式语…
编程与软件工程上首页 8 次 · 2009–2022matt.might.net我的 Forth 与栈机器经历
Yosefk - My history with Forth & stack machines
作者以亲身经历回顾了使用 Forth 语言和栈式机器的历程:既赞叹其简洁优雅、代码量小、可自举的优点,也坦率指出栈操作在实际编程中的痛苦,以及 Forth 社区文化中的问题。
编程与软件工程上首页 8 次 · 2010–2024yosefk.com编辑精选