在“基本类型”那一章,我们学到了字符串以及使用 is_binary/1 函数来检查它:
|
|
在本章,我们将理解二进制数据是什么;它们如何和字符串联系在一起;在Elixir里,被单引号括起来的值,比如 ‘like this’,是什么。
UTF-8和Unicode
一个字符串是一个用UTF-8编码的二进制数据。为了确切理解我们的意思,我们需要理解字节和代码点之间的区别。
Unicode标准给我们所知的许多字符赋予了代码点。比如,字母 a 有代码点 97,而字母 ł 有代码点322。当将字符串 “hełło” 写到磁盘上时,我们需要将它的代码点转换为若干字节。如果我们采用的规则是,一个字节表示一个代码点,那么我们将无法写字符串 “hełło” ,因为它使用了代码点322来表示字母 ł ,而一个字节只能表示 0 到 255的数字。理所当然地,你要正确地在屏幕上读出字符串 “hełło” ,它必须被以某种方式表达出来。这就是编码应用之处了。
用字节的方式来表达代码点的时候,我们需要以某种方式编码它们。Elixir选择UTF-8编码作为它主要的和默认的编码。当我们说一个字符串是一个UTF-8编码的二进制数据,我们的意思是一个字符串是以一种方式,比如指定的UTF-8编码,来组织的表达某些代码点的一块二进制数据。
因为我们有字母,像 ł 被赋予代码点322,所以我们的确需要多于一个字节来表达它们。这就是为什么我们看到的 byte_size/1 和 String.length/1 之间有区别:
|
|
byte_size/1 计算的是底层的字节数,而 String.length/1 计算的是字符数。
注意:如果你用的是Windows,你的终端可能不是默认用UTF-8编码。你可以在运行iex(iex.bat)前通过运行 chcp 65001 来改变你当前会话的编码。
UTF-8需要一个字节来表达字符 h,e 和 o ,但是需要两个字节表达字符 ł 。在Elixir里,你可以用 ? 来获得一个字符的代码点:
|
|
你也可以用String模块里的函数将一个字符串分割为独立字符串组成的列表,其中每一个字符串是长度为一。
|
|
你将看到Elixir已经非常好地支持字符串操作。它也支持许多Unicode操作。实际上,Elixir通过了“The string type is broken”里的所有测试。
然后,字符串只是本文的一部分内容。如果一个字符串是一个二进制数据,并且我们也对它使用了is_binary/1函数,那么Elixir必须有一个底层类型来支持字符串。它的确是这么做的!下面我们来谈谈二进制数据。
二进制数据(和位串)
在Elixir里,你可以用<<>>来定义一个二进制数据。
|
|
一个二进制数据是一个字节的序列。这些字节可以用任何方式来组织,甚至这些字节序列不是有效的字符串:
|
|
字符串的串联操作实际上是二进制数据的串联操作:
|
|
在Elixir里的一个通用技巧是将空字节<<0>>串联在一个字符串后以便看看它内部的二进制表示:0>
|
|
赋给一个二进制数据的每一个数字都表示一个字节,由此它的值最大是255。二进制数据允许给定修饰语来存储大于255的数字,或者转换一个代码点为它的UTF-8编码表示:
|
|
如果一个字节有8位,那么我们只给它一位会发生什么?
|
|
结果是这个值不再是一个二进制数据,而是一个位串 – 一些位。所以一个二进制数据是一个位串,它的位的数量被8整除。
|
|
我们也可以在二进制数据或位串上进行模式匹配:
|
|
注意:在二进制模式中的每一个元素都被期望刚好匹配8位。如果我们想要匹配一个未知大小的二进制数据,在模式的尾部通过使用二进制数据修饰语是可能做到的:
|
|
相似的结果可以用字符串串联符<>来实现:
|
|
关于二进制数据或位串的构造器<<>>的完整指导可以在Elixir官方文档里找到。到此,我们结束了位串,二进制数据和字符串之旅。字符串是UTF-8编码的二进制数据;二进制数据是位串,它的位的数量被8整除。虽然这表明Elixir提供了处理位和字节的灵活性,不过你的99%的时间将用来处理二进制数据,并且使用 is_binary/1 和 byte_size/1 函数。
字符列表
一个字符列表就是一个代码点列表。字符列表可以用单引号括起来的字符字面值创建:
|
|
你可以看到,不是包含字节,一个字符列表包含单引号之间的字符的代码点(注意:默认情况下如果任何整数值在ASCII范围外,则IEx将只是输出代码点)。那么,双引号表示字符串(即二进制数据),单引号表示字符列表(即列表)。
在实践中,字符列表主要用于与Erlang交互的时候,特别是不接受二进制数据作为参数的旧库。你可以用 to_charlist/1 和 to_string/1 函数来转换字符列表为字符串或者反之将字符串转换为字符列表:
|
|
注意:这些函数是多态的。它们不仅可以转换字符列表为字符串,也可以转换整数为字符串,转换原子为字符串,等等。
介绍完二进制数据,字符串和字符列表,接下来是时候讲讲键值对数据结构了。
原文链接: http://elixir-lang.org/getting-started/binaries-strings-and-char-lists.html