Kel*_*vin 7 ruby unicode ruby-1.9
在ruby 1.9.3中,我可以获得字符串的代码点:
> "foo\u00f6".codepoints.to_a
=> [102, 111, 111, 246]
Run Code Online (Sandbox Code Playgroud)
是否有内置方法转向另一个方向,即从整数数组到字符串?
我知道:
# not acceptable; only works with UTF-8
[102, 111, 111, 246].pack("U*")
# works, but not very elegant
[102, 111, 111, 246].inject('') {|s, cp| s << cp }
# concise, but I need to unshift that pesky empty string to "prime" the inject call
['', 102, 111, 111, 246].inject(:<<)
Run Code Online (Sandbox Code Playgroud)
更新(回应尼克拉斯的回答)
有趣的讨论.
pack("U*")始终返回UTF-8字符串,而inject版本返回文件源编码中的字符串.
#!/usr/bin/env ruby
# encoding: iso-8859-1
p [102, 111, 111, 246].inject('', :<<).encoding
p [102, 111, 111, 246].pack("U*").encoding
# this raises an Encoding::CompatibilityError
[102, 111, 111, 246].pack("U*") =~ /\xf6/
Run Code Online (Sandbox Code Playgroud)
对我来说,该inject调用返回一个ISO-8859-1字符串,同时pack返回一个UTF-8.为了防止错误,我可以使用,pack("U*").encode(__ENCODING__)但这使我做了额外的工作.
更新2
显然字符串#<<并不总是正确附加,具体取决于字符串的编码.因此看起来pack仍然是最好的选择.
[225].inject(''.encode('utf-16be'), :<<) # fails miserably
[225].pack("U*").encode('utf-16be') # works
Run Code Online (Sandbox Code Playgroud)
Nik*_* B. 10
你自己的尝试最明显的适应是
[102, 111, 111, 246].inject('', :<<)
Run Code Online (Sandbox Code Playgroud)
然而,这不是一个好的解决方案,因为它只有在初始空字符串文字具有能够保存整个Unicode字符范围的编码时才有效.以下失败:
#!/usr/bin/env ruby
# encoding: iso-8859-1
p "\u{1234}".codepoints.to_a.inject('', :<<)
Run Code Online (Sandbox Code Playgroud)
所以我实际上建议
codepoints.pack("U*")
Run Code Online (Sandbox Code Playgroud)
我不知道你的意思是"只适用于UTF-8".它创建了一个UTF-8编码的Ruby字符串,但UTF-8可以保存整个Unicode字符范围,那么问题是什么呢?注意:
irb(main):010:0> s = [0x33333, 0x1ffff].pack("U*")
=> "\u{33333}\u{1FFFF}"
irb(main):011:0> s.encoding
=> #<Encoding:UTF-8>
irb(main):012:0> [0x33333, 0x1ffff].pack("U*") == [0x33333, 0x1ffff].inject('', :<<)
=> true
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2887 次 |
| 最近记录: |