设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
楼主: DeathKing
打印 上一主题 下一主题

[讨论] Ruby/RGSS Tips 每日一更 [技术区的版聊帖?]

  [复制链接]

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

52
发表于 2010-10-29 15:37:51 | 只看该作者

条件编译

原文:http://rpg.blue/thread-159531-1-2.html

对于一些不是很“动态”的条件分歧,例如对系统的判断等程序开始运行之后一般不会变的
if system_is_windows?
  def do
    #do_in_windows
  end
elsif system_is_linux?
  def do
    #do_in_linux
  end
end

由于ruby的一切都是运行时处理,而没有原生的预编译指令,所以这看起来不像预编译
但是想象一下RM的脚本架构(其他比较大的ruby工程也是像这样),在main之前,定义所有类和方法,这个过程可以近似的认为是编译
如果是做通用库,或者是需要大量执行的方法,效率会有一定提升(吗)

点评

本来我是想和 define? 一起用来解决一些纠结的事的。。。。  发表于 2010-10-29 17:05
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv2.观梦者 (管理员)

八云紫的式神

梦石
0
星屑
609
在线时间
1243 小时
注册时间
2008-1-1
帖子
4282

烫烫烫

51
发表于 2010-10-25 16:04:27 | 只看该作者
又自己抓出来一个ruby1.9小细节
p [1,2,3].to_s #=> "[1,2,3]"  in 1.9
p [1,2,3].to_s #=> "123"  in 1.8

数组的.to_s变成了以人类可读形式输出
rm for linux(wine)制作中,期待夏娜SAMA能实现到webrm上
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
1185
在线时间
1564 小时
注册时间
2008-7-30
帖子
4418

贵宾

50
 楼主| 发表于 2010-10-24 08:12:48 | 只看该作者
本帖最后由 DeathKing 于 2010-10-24 12:23 编辑

欢欢乐乐来循环

经典的for语句:
  1. for i in 0..100
  2.   p "i count #{i}"
  3. end
复制代码
换个马甲如何?
  1. (0..100).each do |i|
  2.   p "i count #{i}"
  3. end
复制代码
原来是重复101次!
  1. 101.times do |i|
  2.   p "i count #{i}"
  3. end
复制代码
想想,是从0数到100:
  1. 0.upto(100) do |i|
  2.   p "i count #{i}"
  3. end
复制代码
我愿意倒着数:
  1. 100.downto(0) do |i|
  2.   p "i count #{i}"
  3. end
复制代码
还没数到100就别停下来
  1. i = 0
  2. while i <= 100
  3.   p "i count #{i}"
  4.   i += 1
  5. end
复制代码
似乎这个更清晰:
  1. i = 0
  2. until i == 101
  3.   p "i count #{i}"
  4.   i += 1
  5. end
复制代码
他们都是循环的快速通道:
for, while, until

Range#each
Integer#times
Integer#upto
Integer#downto
String#upto
String#downto

点评

死循环啊——比如这个RGSS文件【Ruby也可以完成,只不过比较麻烦】 Game.exe exit 多好啊~  发表于 2010-11-9 19:22
moy
goto是在太坏了...  发表于 2010-10-25 08:19
某個integer寫錯了O O  发表于 2010-10-24 12:08
让我们欢乐的goto吧囧  发表于 2010-10-24 09:50
其实还有0.step(100) {|i| p "i count#{i}"} ,顺便那个until里的=应该是==……  发表于 2010-10-24 09:06

See FScript Here:https://github.com/DeathKing/fscript
潜心编写URG3中。
所有对URG3的疑问和勘误或者建议,请移步至发布页面。
欢迎萌妹纸催更
回复 支持 反对

使用道具 举报

Lv1.梦旅人

万物创造者

梦石
0
星屑
54
在线时间
352 小时
注册时间
2008-2-15
帖子
2432
49
发表于 2010-10-23 16:01:11 | 只看该作者
辨析:Kernel#eval、BasicObject#instance_eval、Module#module_eval(Module#class_eval)

(Kernel#)eval把给定的字符串作为代码运算并返回结果。和其它两个不同的是,eval不能传递块。binding可以作为eval的第二个参数传入。

  1. def a
  2.   b = 5
  3.   return binding
  4. end
  5. eval("p b",a) #=>"5"
复制代码
(Basic)Object#instance_eval在一个实例的上下文中eval字符串或块(可以访问类内的方法、变量等)。所有对类的方法或变量的操作只在这个实例中生效,而不会影响类的其它实例。

  1. a = String.new
  2. b = String.new
  3. a.instance_eval{
  4. def foo
  5.   p "foo"
  6. end
  7. }
  8. a.foo                         #=>"foo"
  9. b.foo rescue p nil            #=>nil
  10. p String.method_defined? :foo #=>false
复制代码
Module#module_eval(class_eval)实在模块或类的上下文中eval字符串或块。定义的东西会影响所有实例,主要用于给类或模块定义新的方法。
  1. a = String.new
  2. b = String.new
  3. String.class_eval{
  4. def bar
  5.   p "bar"
  6. end
  7. }
  8. a.bar                         #=>"bar"
  9. b.bar                         #=>"bar"
  10. p String.method_defined? :bar #=>true
复制代码
From mortal hope immortal power springs.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

万物创造者

梦石
0
星屑
54
在线时间
352 小时
注册时间
2008-2-15
帖子
2432
48
发表于 2010-10-22 18:09:39 | 只看该作者
本帖最后由 小幽的马甲 于 2010-10-22 22:39 编辑

用一段简单的代码概括Ruby异常类要点

  1. class Test
  2.   def initialize
  3.     err = nil
  4.     begin
  5.       return unless err.nil?
  6.       raise ArgumentError, "Test"
  7.     rescue IOError
  8.       print "IOError"
  9.     rescue StandardError,ScriptError => err
  10.       print "Error:#{$!}"
  11.       retry
  12.     rescue ArgumentError
  13.       print "ArgumenError"
  14.     rescue
  15.       print "Error"
  16.     else
  17.       print "No Errors!"
  18.     ensure
  19.       print "err = #{err}\n$! = #{$!}"
  20.     end
  21.   end
  22. end
  23. Test.new
复制代码
输出:

  1. Error:Test
  2. err = Test
  3. $! =
复制代码
异常这一块难度不大,知识点不少,所以用这一段概括大部分知识点,没有接触过异常的同学看后也能明白了吧…?
From mortal hope immortal power springs.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

万物创造者

梦石
0
星屑
54
在线时间
352 小时
注册时间
2008-2-15
帖子
2432
47
发表于 2010-10-21 20:50:00 | 只看该作者
几个神奇的位运算应用,问题转自Matrix67-Blog,代码已翻译为Ruby,限于篇幅不转代码的说明了,原文里有(其实用纸和笔画一画很容易想通{:nm_6:} )

二进制中的1有奇数个还是偶数个
我们可以用下面的代码来计算一个32位整数的二进制中1的个数的奇偶性,当输入数据的二进制表示里有偶数个数字1时程序输出0,有奇数个则输出1。例如,1314520的二进制101000000111011011000中有9个1,则x=1314520时程序输出1。
  1. def calc1(x)
  2.   5.times{|i| x ^= x >> (1 << i)}
  3.   return x & 1
  4. end
复制代码
计算二进制中的1的个数
同样假设x是一个32位整数。经过下面五次赋值后,x的值就是原数的二进制表示中数字1的个数。比如,初始时x为1314520,那么最后x就变成了9,它表示1314520的二进制中有9个1。

  1. def calc2(x)
  2.   x = (x & 0x55555555) + (x >> 1 & 0x55555555)
  3.   x = (x & 0x33333333) + (x >> 2 & 0x33333333)
  4.   x = (x & 0x0F0F0F0F) + (x >> 4 & 0x0F0F0F0F)
  5.   x = (x & 0x00FF00FF) + (x >> 8 & 0x00FF00FF)
  6.   x = (x & 0x0000FFFF) + (x >> 16 & 0x0000FFFF)
  7.   return x
  8. end
复制代码
只用位运算来取绝对值
x仍为一个32位整数。

  1. def calc3(x)
  2.   return (x ^ (~ (x >> 31) + 1)) + (x >> 31)
  3. end
复制代码
二进制逆序
    下面的程序读入一个32位整数并输出它的二进制倒序后所表示的数。
    输入: 1314520    (二进制为00000000000101000000111011011000)
    输出: 460335104  (二进制为00011011011100000010100000000000)

  1. def calc4(x)
  2.   x = (x & 0x55555555) <<  1 | (x & 0xAAAAAAAA) >>  1;
  3.   x = (x & 0x33333333) <<  2 | (x & 0xCCCCCCCC) >>  2;
  4.   x = (x & 0x0F0F0F0F) <<  4 | (x & 0xF0F0F0F0) >>  4;
  5.   x = (x & 0x00FF00FF) <<  8 | (x & 0xFF00FF00) >>  8;
  6.   x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16;
  7.   return x
  8. end
复制代码

点评

我有種感覺在RM中用binary計算不比integer快  发表于 2010-10-24 12:08
不得不佩服写出来的那个老外,神乎其技  发表于 2010-10-22 10:35
From mortal hope immortal power springs.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

万物创造者

梦石
0
星屑
54
在线时间
352 小时
注册时间
2008-2-15
帖子
2432
46
发表于 2010-10-20 19:04:53 | 只看该作者
本帖最后由 小幽的马甲 于 2010-10-20 20:21 编辑

基本位运算
在Matrix67Blog看到Pascal版本,觉得很好,于是转为Ruby语言版

顺便说句,Ruby和Pascal的位运算优先级是不同的(和C++大致相同不过似乎也有点小区别),Ruby运算优先级参考本帖29楼

点评

>紫苏 疏忽了……已更正,感谢指出= = 位运算确实有很多巧妙的思路,令人感到非常优美,下次有机会再贴出>  发表于 2010-10-20 20:25
最后三个很有意思,学到了 ^^ 不由念及前年看过的一个 O(1) 取 1 个数的算法,其位的运用真个是鬼斧神工,叹为观止  发表于 2010-10-20 20:14
最后一位变成 0 另一种方式: x & ~1  发表于 2010-10-20 20:01
在最后加一个 1 还是写成 x << 1 | 1 较好,+ 1 一来是有优先级问题,二来效率不及位运算……不过最后还是要看编译器/解释器的优化性能了  发表于 2010-10-20 19:59
From mortal hope immortal power springs.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

万物创造者

梦石
0
星屑
54
在线时间
352 小时
注册时间
2008-2-15
帖子
2432
45
发表于 2010-10-19 21:27:34 | 只看该作者
本帖最后由 小幽的马甲 于 2010-10-19 22:09 编辑

简单地说下Symbol类。
Symbol类似一个静态的String。类似于:aaa之类的字面值都是Symbol,可以调用String#to_sym或String#intern把不包含空字符的字符串转化为符号,调用Symbol#to_s或Symbol#id2name把符号转化为字符串。
作为字面值使用时,冒号后面跟双引号和单引号结果是不同的,要注意

  1. a = "abc"
  2. p :"#{a}" #=> :abc
  3. p :'#{a}' #=> :'#{a}'
复制代码
Symbol同样也有%号表示法:%s。

  1. p %s{aaa}         #=>:aaa
  2. p %s{aaa bbb}     #=>:"aaa bbb"
  3. p %s{aaa\n}       #=>:"aaa\\n"
复制代码
Symbol类有一个类方法:Symbol.all_symbols,用于以数组的形式返回所有已定义的符号对象。

Symbol一个很重要的性质是,字面值一样的Symbol都是同一个Object

  1. str1 = "aaa"
  2. str2 = "aaa"
  3. p str1.equal? str2   #=>false
  4. sym1 = :aaa
  5. sym2 = :aaa
  6. p sym1.equal? sym2   #=>true
复制代码
这使得它在执行比较的时候比String效率高(Symbol继承了Object的self==other,String则是重新定义,让两个字符串逐字比较),所以当String仅仅用来作为一个标志的时候可以考虑替换为Symbol。

  1. def move(direction)
  2.   @x += 1 if direction == :right
  3.   @x -= 1 if direction == :left
  4.   @y += 1 if direction == :up
  5.   @y -= 1 if direction == :down
  6. end
复制代码
(Ruby1.9相关)
在Ruby1.9里,Hash可以这么定义:
  1. {a:"aaa",b:"bbb"}
复制代码
它等价于
  1. {:a => "aaa", :b => "bbb"}
复制代码
在Ruby1.9中,Symbol类加入了大量的实例方法,大部分都是String类的实例方法,如capitalize、downcase、encoding
  1. p :aaa.upcase  #=>:AAA
复制代码
25楼的67在说明&的应用时给Symbol定义了to_proc方法,在Ruby1.9就不用这样,Symbol自带to_proc
  1. words = %w(hello kitty not world)
  2. list = words.map(&:capitalize)
复制代码
ok,得到了第一个字母大写的字符串数组了

顺便说一句,默认RGSS看似没怎么用Symbol,但你不知不觉地已经用了很多了。
  1.   attr_accessor :next_scene               # 切换待机中的画面 (文字列)
复制代码

点评

嗯,其实 1.9 介绍符号键 Hash 语法的目的就是为了鼓励使用符号,符号常量池的机制是牺牲了创建时间,换来空间和比较时间  发表于 2010-10-20 10:05
From mortal hope immortal power springs.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
44
发表于 2010-10-18 10:50:40 | 只看该作者
本帖最后由 紫苏 于 2010-10-19 00:48 编辑

连续弄了三天编码,同学们想必都有点腻了,老实说我自己也有点反胃,还剩下 I/O 部分的一些编码相关内容,就留待改日补完了吧!
(以下提及的 Ruby,均指官方的 Ruby 实现)
今天我们来简单的看一下提升 Ruby 1.9 性能的大功臣——YARV。
YARV,全称是 Yet Another Ruby VM,VM 的全称是 Virtual Machine。这个名称,翻译为中文,就是“又一个 Ruby 虚拟机”。这种以 `Yet Another' 形式开头的命名是一种黑客行话,在有英语语感的程序员看来,这种命名有三分幽默诙谐之感,在业内十分受欢迎。
Ruby 的虚拟机,就和 Oracle 的 JVM(Java 虚拟机)、微软的 CLR(.NET) 一样,是一种由软件实现的虚拟的机器构架,有着自己的指令集,并可以像物理机器一样执行指令。这种针对某个(家族)语言设计的虚拟机被称为进程虚拟机,因为它只是给操作系统上某一个进程(解释器)服务的;与之并列的是系统虚拟机,它需要分享整个系统的物理硬件资源,比如我们 VirtualBox 下的 Guest OS,就是一种虚拟一整个操作系统的技术。
为什么 Ruby 需要虚拟机?大多数程序员都是人类,人类写的代码,通常是按照人类思考的方式去对机器下达命令,但并不一定有着最高的执行效率。同样效果的代码,在很高程度上都存在着另一份更高效的途径,而我们把找寻并迈向这个途径的过程称为优化。对于编译性语言,我们可以设计一个具有自动优化(同时从源代码层、汇编层)的编译器来一次性最优化我们的代码,并编译为机器码;而对于解释性语言,由于我们是在动态地解释脚本,所以不能把代码一次性地优化并编译为机器码。
Ruby 1.8 的解释器被称为 Matz's Ruby Interpreter(MRI),它解析 Ruby 源文件,并生成一个语法树,然后直接在这个语法树上进行动态求值。这样的过程是毫无优化的。目前主流的解决方案大致可分为两种,其一是采用预编译(Ahead-of-time Compilation),其二是采用即时编译(Just-in-time Compilation)。就 Ruby 1.9.2 的 YARV 来说,它只有前者。所谓预编译,顾名思义,就是预先把代码编译。什么,我之前不是说过“不能把代码一次性地优化并编译为机器码”?是的,的确是这样,但这里的“预编译”不是编译为机器码,而是编译为一种中间代码,通常被称为字节码。字节码和机器码的不同在于,前者是平台无关的,且具备动态性,是由解释器(虚拟机)动态解析的,而不像机器码是直接交给底层的硬件(CPU)去执行。在把可供人类阅读的源代码编译为字节码的过程中,我们就可以进行各式各样的优化,最后产生的字节码,在大部分场合下都比原来的源代码更加高效。
(题外话: YARV 的作者 Sasada Koichi 也曾尝试过引入 JIT 即时编译,进一步提高 YARV 的性能,但 YARV 的主页很久没有更新了,也不知进展如何。JIT 本身是一个十分复杂、很难实现的技术,可能对他来说并不是一个人能实现的了的。也许,Ruby 2.0 会……)
YARV 就是这样的一个虚拟机,它忠心耿耿地优化着我们所写下的 Ruby 代码,几十年如一日,在大量的 Benchmark 测试下,展示了 Ruby 1.9 几近于 Ruby 1.8 两倍的性能。

在 Ruby 1.9 的官方实现(CRuby)中,有了一个内置的类,叫做 RubyVM。它提供给了用户一些在运行时获取 YARV 状态的实用接口,这里介绍几个比较重要的类和方法。
RubyVM::InstructionSequence,这是一个 YARV 指令序列的类,它可以用来动态地编译、反汇编、执行 Ruby 代码。

  1. instrs = RubyVM::InstructionSequence.compile <<-START
  2.         a = 0
  3.         a = a + 1
  4.         a += 2
  5.         p a
  6. START

  7. puts instrs.disassemble
复制代码
这里我们先编译了四行简单的 Ruby 代码,并建立了一个 RubyVM::InstructionSequence 对象。之后我们把反汇编后的指令序列按照 Ruby 提供的可供人类阅读的方式打印了出来,输出:

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] a
0000 trace            1                                               (   1)
0002 putobject        0
0004 setlocal         a
0006 trace            1                                               (   2)
0008 getlocal         a
0010 putobject        1
0012 opt_plus
0013 setlocal         a
0015 trace            1                                               (   3)
0017 getlocal         a
0019 putobject        2
0021 opt_plus
0022 setlocal         a
0024 trace            1                                               (   4)
0026 putnil
0027 getlocal         a
0029 send             :p, 1, nil, 8, <ic>
0035 leave

可以看到,四行 Ruby 代码在 YARV 层实际上就是这样的指令序列。我们可以通过 RubyVM::INSTRUCTION_NAMES 来打印出 YARV 所有的指令:

["nop", "getlocal", "setlocal", "getspecial", "setspecial", "getdynamic", "setdy
namic", "getinstancevariable", "setinstancevariable", "getclassvariable", "setcl
assvariable", "getconstant", "setconstant", "getglobal", "setglobal", "putnil",
"putself", "putobject", "putspecialobject", "putiseq", "putstring", "concatstrin
gs", "tostring", "toregexp", "newarray", "duparray", "expandarray", "concatarray
", "splatarray", "checkincludearray", "newhash", "newrange", "pop", "dup", "dupn
", "swap", "reput", "topn", "setn", "adjuststack", "defined", "trace", "definecl
ass", "send", "invokesuper", "invokeblock", "leave", "finish", "throw", "jump",
"branchif", "branchunless", "getinlinecache", "onceinlinecache", "setinlinecache
", "opt_case_dispatch", "opt_checkenv", "opt_plus", "opt_minus", "opt_mult", "op
t_div", "opt_mod", "opt_eq", "opt_neq", "opt_lt", "opt_le", "opt_gt", "opt_ge",
"opt_ltlt", "opt_aref", "opt_aset", "opt_length", "opt_succ", "opt_not", "opt_re
gexpmatch1", "opt_regexpmatch2", "opt_call_c_function", "bitblt", "answer"]

值得注意的还有一个方法:
  1. p RubyVM::InstructionSequence.compile_option
复制代码
输出:

{:inline_const_cache=>true, :peephole_optimization=>true, :tailcall_optimization
=>false, :specialized_instruction=>true, :operands_unification=>false, :instruct
ions_unification=>false, :stack_caching=>false, :debug_level=>0}

这其实是 YARV 使用的一些优化方法。就目前来说,有很多高级优化技术,YARV 都还没有使用上,可见 Ruby 的性能提升还是有很大空间的。

点评

难说,毕竟各大 Ruby 虚拟机都在进行激烈的竞争,指不定哪天谁把谁超了 o.o YARV 作为官方版压力很大  发表于 2010-10-19 00:45
我很好奇Rubinius和YARV相比性能如何= =  发表于 2010-10-18 22:15
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
61
在线时间
24 小时
注册时间
2008-8-5
帖子
1924
43
发表于 2010-10-17 05:24:28 | 只看该作者
本帖最后由 紫苏 于 2010-10-17 05:27 编辑

继续一些和 Ruby 1.9 字符串编码有关的内容——




新的转义序列:\u
在字符串字面值中指定 \u 可以用来表式一个 Unicode 字符,后面紧跟着一个 16 位(双字节 UTF-16BE)十六进制数字:

  1. #coding: GBK

  2. str = "测试".encode(Encoding::UTF_16BE)
  3. p "\u6d4b\u8bd5".encoding
  4. p "\u6d4b\u8bd5".encode(Encoding::GBK, Encoding::UTF_8)
  5. p "\u6d4b\u8bd5".encode(Encoding::GBK)
复制代码
(注:这里的源文件编码使用 GBK 是因为我测试时的源文件是 GBK 编码,下同。)
输出:

#<Encoding:UTF-8>
"测试"
"测试"

当字符串中包含 \u 序列时,尽管你指定的是 UTF-16 大端序的 Unicode 字符,该字符串还是会被自动编码为 UTF-8,并相应设置字符串的编码成员为 UTF-8(默认是和源文件编码相同),所以这里第一行打印出了一个 UTF-8 的 Encoding 对象。

`\u6d4b' 和 `\u8bd5' 这两个字符分别是 `测' 和 `试' 的 UTF-16BE 内码。后两行输出语句是完全一致的,因为字符串对象内部维护着一个编码对象的域,所以 String#encode 可以根据这个域来进行编码。这里它知道 "\u6d4b\u8bd5" 的编码为 UTF-8,所以是否手动指定源编码都无所谓了。由于我测试时使用的是 Windows 的字符终端(即被称为“命令提示符”的控制台),它使用的编码取决于 locale,而我的 locale 的代码页是 GBK,所以只有当我们把这个字符串编码回 GBK 后,才能正常地在字符终端上显示“测试”这两个字。

注意我们这里用的是 Encoding::UTF_8 等常量,而不是 "UTF-8" 这样的字符串,这重利用了预先生成的 Encoding 对象,避免了字符串对象的创建,给 Ruby 的堆和 GC 减少了压力。




String 进行了 Comparable 的 mixin,糅合了一个 `==' 方法,但 String 类对它进行了覆盖,使其比较字符串内容而不是对象的身份。现在 String 多了编码的成员,但 == 并不会进行不同编码间相同字符串的验证,它只是简单地比较每一个字节。




String#codepoints 也是一个新的方法。它返回字符串中所有代码点的枚举器(关于枚举器,我们改天再讨论,如果你还没有概念,可以想象成一个集合,与数组相似但还并未完全是数组)。代码点是一个字符在代码页中对应的、唯一的整数,这些整数的集合就形成了一个“代码空间”(即字符集),比如 7 位 ASCII 字符集,就有 128 个代码点,分别表示 128 个不同的字符。在一个字符集中,一个代码点和一个字符是有一对一关系的,和字节是两码事。比如 `测' 这个字符在 UTF-8 里占据 3 个字节,但是与之对应的只有一个代码点。

  1. #coding: UTF-8

  2. p "测试".codepoints.to_a
复制代码
输出:

[27979, 35797]

你可能发现这两个数字刚好是我们之前看到的 `\u6d4b'、`\u8bd5' 的十进制表示,但这并不代表 UTF-8 和 UTF-16 没区别。UTF-8 和 UTF-16 等 Unicode 编码家族都可以使用相同的代码点和相同的 Unicode 平面,但是在数据存储的细节上有不同。




String#force_encoding,它可以强行改变字符串对象的编码属性(一个 Encoding 成员变量),但它并不会改变底层的内码,而只是改变其它编码的方法(如 String#encode)处理字符串时的行为。
  1. #coding: GBK

  2. str_utf_8 = "测试"
  3. str_gbk = str_utf_8.clone
  4. str_gbk.force_encoding(Encoding::UTF_8)

  5. p str_gbk.encode(Encoding::GBK)
复制代码
输出:

1.rb:7:in `encode': "\xB2" on UTF-8 (Encoding::InvalidByteSequenceError)
        from 1.rb:7:in `<main>'

String#encode 把 str_gbk 当做 GBK 编码来处理,而 str_gbk 的内码实际上还是 UTF-8,所以抛出了这个异常。用户可以用 String#valid_encoding? 来对此进行判断。

点评

沙发~  发表于 2010-10-17 06:43
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-25 12:44

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表