3.5 字节与字节串
字节是从 0 到 255 的精确整数。谓语 byte? 用于识别表示字节的数值。
字节串类似于字符串(见字符串(Unicode)),不过其内容为字节序列而非字符序列。 字节串可在处理纯 ASCII 而非 Unicode 的应用中使用。字节串的打印形式专门支持这种用法, 因为字节串的打印除了带有 # 前缀外,和字节串的解码一致。不可打印的 ASCII 字符或字节串中的非 ASCII 字节会被写作八进制记法。
The Racket Reference的Reading Strings一节中阐述了字节串语法的要点。
> #"Apple" #"Apple"
> (bytes-ref #"Apple" 0) 65
> (make-bytes 3 65) #"AAA"
> (define b (make-bytes 2 0)) > b #"\0\0"
> (bytes-set! b 0 1) > (bytes-set! b 1 255) > b #"\1\377"
字节串的 display 形式会将其原始字节写入到当前输出端口中(见 Input and Output)。技术上来说,正常串(即字符串)的 display 形式会将 UTF-8 编码的该串打印到当前输出端口中,因为输出是以字节来定义的。然而,display 一个字节串写出未经编码的原始字节。按照同样的思路,当本文档显式输出时, 从技术上来说,它显示的输出是 UTF-8 编码的形式。
> (display #"Apple") Apple
> (display "\316\273") ; 与 "λ" 相同 λ
> (display #"\316\273") ; λ 的 UTF-8 编码 λ
为了显式地在字符串和字节串之间转换,Racket 直接支持了三种类型的编码:UTF-8、Latin-1 和当前地区的编码。字节到字节(特是从 UTF-8 和到 UTF-8)转换的通用功能用于填补任意编码之间的空隙。
> (bytes->string/utf-8 #"\316\273") "λ"
> (bytes->string/latin-1 #"\316\273") "λ"
> (parameterize ([current-locale "C"]) ; C 地区只支持 ASCII, (bytes->string/locale #"\316\273")) ; 所以... bytes->string/locale: byte string is not a valid encoding
for the current locale
byte string: #"\316\273"
> (let ([cvt (bytes-open-converter "cp1253" ; 希腊字母代码页 "UTF-8")] [dest (make-bytes 2)]) (bytes-convert cvt #"\353" 0 1 dest) (bytes-close-converter cvt) (bytes->string/utf-8 dest)) "λ"
The Racket Reference的Byte Strings一节中提供了关于字节串及其过程的更多信息。