3.5 字节与字节串

字节是从 0255 的精确整数。谓语 byte? 用于识别表示字节的数值。

例如:
> (byte? 0)

#t

> (byte? 256)

#f

字节串类似于字符串(见字符串(Unicode)),不过其内容为字节序列而非字符序列。 字节串可在处理纯 ASCII 而非 Unicode 的应用中使用。字节串的打印形式专门支持这种用法, 因为字节串的打印除了带有 # 前缀外,和字节串的解码一致。不可打印的 ASCII 字符或字节串中的非 ASCII 字节会被写作八进制记法。

+The Racket ReferenceReading 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 ReferenceByte Strings一节中提供了关于字节串及其过程的更多信息。