• Ruby:字符集和编码学习总结


    背景

    Ruby直到1.9版本才很好的支持了多字节编码,本文简单总结了今天学习的关于Ruby编码方面的知识。

    字符串可以使用不同的编码

    在.NET中字符串的编码是一致的,Ruby允许字符串有不同的编码,当时我就在想:如果两个不同编码的字符串相加会出现什么结果?

    测试程序

     1 # coding: utf-8
     2 
     3 str_utf8 = "hi 段"
     4 puts str_utf8.size                                # 4
     5 puts str_utf8.bytesize                            # 6
     6 puts str_utf8 .encoding                         # UTF-8
     7 str_utf8.each_byte {|b| print "%02X," % [b]}      # 68,69,20,E6,AE,B5,
     8 puts
     9 
    10 puts
    11 
    12 str_gb2312 = "hi 段".encode("gb2312")
    13 puts str_gb2312.size                            # 4
    14 puts str_gb2312.bytesize                        # 5
    15 puts str_gb2312 .encoding                         # GB2312
    16 str_gb2312.each_byte {|b| print "%02X," % [b]}     # 68,69,20,B6,CE,
    17 puts

    输出结果

    1 4
    2 6
    3 UTF-8
    4 68,69,20,E6,AE,B5,
    5 
    6 4
    7 5
    8 GB2312
    9 68,69,20,B6,CE,

    备注:UTF-8对英文采用1个字节,对中文采用三个字节。GB2312对英文采用1个字节,对中文采用两个字节。

    编码转换

    编码转换可以采用String::encode("目标编码名称")来完成,如果编码之间的转换兼容,返回编码后的字符串,否则会抛出编码转换异常。

    测试程序

    1 begin
    2     puts "".encode("ascii")
    3 rescue Exception => e
    4     puts e.class
    5 end
    6 
    7 puts "".encode("gb2312")

    输出结果

    1 Encoding::UndefinedConversionError
    2

    备注:encode会返回一个和元字符串序列一样的字符串序列,只是内部的字节序列改变了。

    编码强制

    编码强制是指在不改变字节序列的情况下改变对字节的解释方式,编码强制:String::force_encoding("强制编码")。

    测试程序

     1 utf8_str = "xE6xAExB5".encode("utf-8")
     2 puts utf8_str.encoding() # UTF-8
     3 puts utf8_str.size # 1
     4 puts utf8_str.bytesize # 3
     5 
     6 ascii_str = "xE6xAExB5".force_encoding("ascii")
     7 puts ascii_str.encoding() # US-ASCII
     8 puts ascii_str.size # 3
     9 puts ascii_str.bytesize # 3
    10 puts ascii_str.valid_encoding? # false

    输出结果

    1 UTF-8
    2 1
    3 3
    4 US-ASCII
    5 3
    6 3
    7 false

    备注:String::valid_encoding?可以判定是否是有效的强制。

    不同编码的字符串相加后是啥结果?

    这个问题的答案很简单:如果两个字符串的编码兼容,则返回字符集最大的编码,否则跑出不兼容异常。你可以自己检查兼容性:Encoding.compatible?。

    测试程序

    1 str_ascii = "hi ".encode("ascii")
    2 str_utf8 = ""
    3 puts str_ascii.encoding
    4 puts str_utf8.encoding
    5 puts Encoding.compatible?(str_ascii.encoding, str_utf8.encoding)
    6 puts (str_ascii + str_utf8).encoding
    7 puts (str_utf8 + str_ascii).encoding

    运行结果

    1 US-ASCII
    2 UTF-8
    3 UTF-8
    4 UTF-8
    5 UTF-8

    一直没使用过的u和x

    几乎所有的语言都支持这两个转义字符,允许我们使用uXXXX指定Unicode码点对于的字符,通用也运行我们使用xXX指定字节。

    测试程序

    1 puts "" #
    2 puts "xE6xAExB5" #
    3 puts "u6BB5" #

    输出结果

    1 #
    2 #
    3 #

    使用Sublime开发Ruby时,输出到控制台的字符串为啥不能使用多种编码?

    测试程序

    1 puts ""
    2 puts "".encode("GB2312")

    在Sublime中的输出结果

    1 [Decode error - output not utf-8]

    在控制台的输出结果

    原因分析

    Sublime之所以失败是因为Sublime重定位了默认标准输出流,而重定位后的流不支持混合多种编码,说白了:你没法在一个文件中保存两种编码的字符串。

    备注:Sublime中的失败不是Ruby导致的,是Sublime自身的问题。

    如何解决?

    Sublime默认只能接收UTF8编码,因此必须转换为UTF8编码。

    1 # 默认是UTF8编码,不用处理。
    2 puts ""
    3 # 执行windows命令必须使用GB2312编码。
    4 command = "echo 段".encode("GB2312")
    5 # 命令执行的结果想输出到Sublime必须使用UTF8编码。
    6 puts `#{command}`.encode("utf-8")

    输出结果

    1  # 输出结果
    2 3

    备注

    字符串、字符集和编码算是刚入门,有机会还得继续学习。

  • 相关阅读:
    课后作业-阅读任务-阅读笔记-4
    《团队--学生成绩管理-阶段互评》
    《团队-学生成绩管理-阶段互评》
    团队编程项目作业4-开发文档
    阅读任务--阅读提问-3
    课后作业-阅读任务-阅读笔记3
    课后作业-阅读任务-阅读提问-3
    课后作业-阅读任务-阅读笔记-3
    结对编程项目作业5
    结对编程项目作业4
  • 原文地址:https://www.cnblogs.com/happyframework/p/3275367.html
Copyright © 2020-2023  润新知