美文网首页Ruby
Ruby or Rails 学习总结 3

Ruby or Rails 学习总结 3

作者: Qo_Tn | 来源:发表于2020-04-13 10:32 被阅读0次

Qo_Tn


第五章学习

5.1 模块的定义与使用

  1. 模块的定义
    模块和类相似,也是由一组方法和常量组成。
    对于类来说模块没有实例,但可以将模块的功能添加到类或特定的对象中。

  2. 定义模块
    关键字 module 、include

    module  方法名
        模块体
    end
    
  3. 混含操作
    类中可以包含多个模块,但是类不能继承多个类

  4. 模块实现命名空间
    所谓命名空间,就是一种将程序库名称封装起来的方法,它就像在各个程序库中立起一道道围墙。如果在同一个命名空间里面出现相同的方法名,编译就会出现错误。

    例如:

    # 模块的创建与使用
    module ModuleName
        def moduleInfo
            puts "我是模块里面的方法成员"
        end
        def self.showInfo
            puts "我是模块里面的类方法成员"
        end
    end
    ModuleName.showInfo
    
    #模块实例
    module Past
        def pastInfo
            puts "时间总是让人无能为力,因为你无法改变它。"
        end
    end
    class PastInclude
        include Past
    end
    pastInclude=PastInclude.new
    pastInclude.pastInfo
    
    #模块实现命名空间
    module ModulePlace
        class FirstPlace
            def moduleInfo
                puts "我是模块定义的ModulePlace命名空间中的moduleInfo方法"
            end
        end
    end
    module SmodulePlace
        class SecondPlace
            def moduleInfo
                puts "我是模块定义的SmodulePlace命名空间中的moduleInfo方法"
            end
        end
    end
    firstPlace=ModulePlace::FirstPlace.new
    firstPlace.moduleInfo
    SecondPlace=SmodulePlace::SecondPlace.new
    SecondPlace.moduleInfo
    

5.2 BEGIN块和END块

  1. BEGIN 块 和 END块

    • 类似于开始,结束
    BEGIN{
        初始化代码块
    }
    END{
        释放的代码块
    }
    
  2. at_exit 块

    • at_exit 块和 END块相似,都是在程序结束后执行,但是at_eixt块执行的时间要比END晚。

    例如:

    # BEGIN 块和 END 块
    BEGIN{puts "武林大会正式开始!正在寒暄中....."}
    BEGIN{puts "西毒欧阳锋天下第一"}
    BEGIN{puts "东邪黄岛主天下第二"}
    BEGIN{puts "南帝一定大师天下第二"}
    BEGIN{puts "北丐洪七公天下第三"}
    END{puts "中神通王重阳不参赛"}
    END{puts "第一"}
    END{puts "第二"}
    END{puts "第三"}
    
    #at_exit
    BEGIN{puts "武林大会正在开始!正在寒暄中......."}
    at_exit{puts "三号学生"}
    at_exit{puts "学习好是第一"}
    at_exit{puts "人品好是第二"}
    at_exit{puts "气质好是第三"}
    END{puts "三好学生是我的偶像"}
    

5.3 加载其他文件

  1. 加载其他文件 (require、load)

    • load 和 require 加载其他文件

    • load 功能强大,除Ruby源文件外,还可以加载其他语言源文件

    • require 语法

      require "源文件"   
      require "源文件全名"
      
    • require 方法可以重复使用,但只能加载一次。而 load 方法却可以加载多次。

  2. 调用内部文件(include、extend)

    • include 主要是将一个模块混含到一个类中,以此来访问模块中的实例成员
    • extend 方法主要是用来在一个对象中引入一个模块,这个类也具备了这个模块的方法,类似于继承

    例子:

        # a.rb文件
    module ModuleName
        def go
            puts "汽车正在公路上行驶"
        end
        def self.show
            puts "我是Modeule文件下面的M文件中的mudleY.rb文件中的内容"
        end
    end
    ModuleName.show
    
    # hello.rb 文件
    def hello
        puts "Hello World!"
    end
    
    # b.rb 文件
    puts "加载Module文件夹下的M文件下的ModleY.rb文件"
    load "0500第五章内容.rb"
    
    require "#{File.dirname(__FILE__)}/hello"
    hello
    
            
    #include 和extend
    module Mood
        def say
            p "hello, everyone!"
        end
    end
    
    class Person
        extend  Mood
    end
    
    person=Person.new
    person.extend(Mood)
    person.say
    

5.4 别名和定义

  1. alias 或 alias_method : 为方法或者全局变量添加别名。�

    • 给方法添加别名时,别名方法和原始方法是绑定的。即使重新定义了原始方法,别名方法仍保持着重定之前的老方法的特性
  2. 定义的操作(defined? 、undef)

    • 判断定义 和 释放定义
    • 判断定义 是判断某个表达式是否已经完成定义需要使用 defined?语法,完成返回 false ,否则返回 保存表达式类型的字符串。
    • 语法 : defined?表达式

    defined?的返回值表:

    返回的字符串 解释
    s�uper 当super调用可用时返回的字符串
    method 使用defined? 判断的方法已经被定义时 返回的字符串
    yield 如果“yield”可用时,返回的字符串
    self 如果self可用,则返回“self”
    nil 当对象为 nil 时返回该字符串
    true 当表达式为true 时返回的值
    false 当表达式为 false 时返回的值
    assignment 当一个局部变量已经被定义,但未赋值时所返回的值
    local-variable 当一个局部变量已经被赋值时所返回的值
    local-variable(m-block) 当一个局部变量已经被赋值,并且处于一个代码块中时所返回的字符串
    global-variable 当一个全局变量已经被赋值时返回的字符串
    instane-variable 当一个实例变量已经被赋值时返回的字符串
    constant 当一个常量已经被赋值时所返回的字符串
    class-variable 当一个类变量已经被赋值时所返回的字符串
    expression 只是一个表达式时返回的值
    • 释放定义 语法: undef 方法名[方法1,...]

    示例:

    # 别名和定义
    def name
        puts "我是定义的name 方法"
    end
    alias new_name name
    
    def name
        puts "重新定义后的name 方法"
    end
    puts name
    puts new_name
    
    # dfined?表达式
    class Return
        def Replay
            puts "你知道08版欧阳克是谁顶的吗?"
            puts defined?"真的很好"
        end
    end
    
    ret=Return.new
    puts defined?ret.Replay
    ret.Replay
    
    p  defined?true
    
    
    #undef 释放定义
    
    class Fly
        def go
            puts "飞机正在起飞ing....."
        end
    end
    
    fly=Fly.new
    undef go
    puts defined?fly.go
    

5.5 method_missing 的使用

  1. method_missing 的使用

    • 使用对象调用一个类或者一个实例的某个方法时,如果系统没有找到这个方法时,系统会自动调用一个函数,而这个函数就称为自动提供错误处理的回调函数。
    • 在 Ruby 语言中,自动调用提供错误处理的回调函数属于动态语言特性的一种。这里提供 method_missing 方法就是用于处理搜索不到方法的错误。
    #method_missing 的使用
    class Missing
        def miss
            puts "我没有丢失miss的方法"
        end
        def method_missing pd
            puts "不好意思,在Missing类中不存在#{pd.to_s}的实例方法"
        end
        def self.method_missing pd
            puts "不好意思,在Missing 类中不存在#{pd.to_s}类方法"
        end
    end
    
    missing=Missing.new
    puts missing.miss
    puts missing.nihao
    puts Missing.Mynihao
    
    
    class Find
        def self.post
            puts "使用的地址是: www.baidu.com"
        end
        def self.method_missing pd
            puts "地址出错,请检查...出错地址是:https"
        end
    end
    puts Find.post
    puts Find.show
    
    class Roman
        def self.method_missing name, *args
            roman=name.to_s
            if(roman=~/^[IVXLC]*$/)
                roman.gsub!("IV","IIII")
                roman.gsub!("IX","VIIII")
                roman.gsub!("XL","XXXX")
                roman.gsub!("XC","LXXXX")
                return (roman.count("I")+roman.count("V")*5+roman.count("X")*10+roman.count("L")*50+roman.count("C")*100)
            else
                super(name, *args)
            end
        end
    end
    

5.6 duck typing 特性

  1. duck typing 特性
  • duck typing 是一种实用主义的面向对象方法,属于动态语言的一种。它对对戏那个没有约定,只是在运行时进行检查,如果作为参数的对象拥有需要的方法和属性,就符合使用的要求。对 duck typing 做一个感性认识就是:"当看到一只天鹅走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子、那这只天鹅就可以被称为鸭子"。

  • duck typing 同样也可以实现在静态语言中,只不过要在编译时识别和指定这些动态类。

    # duck typing
    class MusicAvi
        def play
            puts ".avi 格式的视频已经添加到列表中"
        end
    end
    
    class Music3gp
        def play
            puts ".3gp格式的视频可以播放"
        end
    end
    
    class MusicRmv
        def play
            puts ".rvm 的格式的视频在这里也可以播放,不行,你试试"
        end
    end
    
    class MusicRmvb
        def play
            puts ".rmvb格式的视频更不用说了"
        end
    end
    
    def playMusic(music)
        music.play
    end
    
    playMusic MusicAvi.new
    playMusic Music3gp.new
    playMusic MusicRmv.new
    playMusic MusicRmvb.new
    

5.7 Proc对象

---------- 难点 -----------

  1. Proc 对象

    • Proc 对象 是对块及其局部变量的作用域进行对象化处理后得到的过程对象。导入到Proc内的局部变量没有作用域的问题,也就是说,Proc内的局部变量会让你得到动态局部变量的效果。
    • Proc 可以向其他方法传递一块作为参数的代码,类似处理数据
    • 创建 pr=Proc.new{puts "创建一个Proc对象"}
    • 执行 pr.call
    • Proc 对象 是一个 代码块 的封装体, 在 Ruby 定义方法时,在方法的最后一个形参前添加一个“&”符号,那么程序会将这个形参作为一个Proc对象来处理。
    • 使用 proc 方法生成 Proc 对象
    # Proc 对象
    
    def call_proc(pr)
        a="我是在call_some_proc中声明的变量"
        puts a
        pr.call
    end
    
    a="我是在外部声明的变量"
    pr=Proc.new{puts a}
    pr.call
    call_proc(pr)
    
    # &符号举例
    def grab_blc(&blc)
        blc.call
    end
    grab_blc{puts "知道我是谁吗,郑重的告诉你,我是Proc对象"}
    
    # 用 Proc 对象生成proc
    Value=proc do |value|
        puts "使用Proc对象执行代码块,传递的值是:#{value}"
    end
    
    Value.call("Happy New Year 2011")
    def info
        yield "Proc 对象作为一个参数传递"
    end
    info &Value
    

5.8 eval方法

  1. eval

    • eval 函数来动态执行字符串保存的 Ruby 代码,当 eval 函数获得保存代码的字符串之后,让解释器来解释这段代码。
    • eval 效率相比于正常要低
    # eval 方法
    puts "在字符串中创建方法名称为evalShow"
    str="def evalShow;puts '我是在字符串中创建的方法,名称是evalShow';end"
    eval(str)
    
    # eval 效率测试
    puts "下面的这段代码是使用eval动态执行的代码"
    count=Array.new
    startTime=Time.now
    puts "使用eval动态执行的代码的开始时间是:"+startTime.to_s
    str="abcdefghijklmnopqrstuvwxyz"
    for a in 1..10000
        eval("count<<str")
    end
    endTime=Time.now
    puts "使用eval动态执行的代码的结束时间是:"+endTime.to_s
    puts "使用eval动态执行的代码的时间间隔是:"+(endTime-startTime).to_s
    
    puts "下面这段代码正常的程序执行的代码"
    count=Array.new
    startTime=Time.now
    puts "使用正常的程序执行的代码开始的时间是:"+startTime.to_s
    str="abcdefghijklmnopqrstuvwxyz"
    for a in 1..10000
        count<<str
    end
    endTime=Time.now
    puts "使用正常的程序执行代码的结束时间是:"+endTime.to_s
    puts "使用正常的程序执行的代码中间时间间隔是:"+(endTime-startTime).to_s
    

5.9 异常处理机制

  1. Exception类 或 其派生类(特殊类对象)

    异常类型 异常说明 异常原因
    untimeError 运行时异常,当调用了raise 却未指定异常时,就会引发该异常 i=4 raise "bigger than 3 if i>3"
    NoMethodError 对象找不到一个对应的方法时,就会抛出该异常 class Catch ... end catch=Catch.new catch show
    NameError 解释器碰到一个不能解析为变量或者方法名的表示符 a=som_random_identifier
    IOError 当Ruby读取关闭的流,写入只读的流,或者类似的操作均会发生该异常 STDIN puts "不能写入的流"
    Errono::error 与文件IO相关的一组错误 file1=File.new("one")
    TypeError 方法介绍到不能处理的参数 IO read(-1)
    ArgumentError 传递参数的数目出错 class Catch def walk name puts "走路" end catch=Catch.new catch walk
  2. begin...end 块处理异常 resure 捕获

  3. Ruby 中 的异常主要依赖于rescue 和 ensure 来完成,但是两者的任务�是不同的,rescue块主要是将程序从异常中解救出来,而ensure主要用于保证系统的资源回收

  4. 捕获 系统异常 rescue异常类=>实例名

  5. 获取异常常用的方法主要有 backtrace方法、创建实例的new方法 以及to_s 和 message方法

  6. 显示异常 及 捕获异常

    #异常处理
    puts "------- 下面的代码是使用rescue来捕获异常的实例-------"
    begin
        class Swim
            def swimming name
                @name=name
                puts "一条被叫做#{@name}的美人鱼在水里游来游去"
            end
            swim=Swim.new
            swim=swimming
        rescue
            puts "swimming 的参数不一致,导致出现异常,请注意"
        end
    end
    
    
    puts "------- 不同的异常采用不同的异常处理块-------"
    begin
        class Fly
            def flying speed
                @speed=speed
                puts "飞机正以#{@speed}的速度向前飞行"
            end
        end
        fly=Fly.new
        fly.show
        fly.flying
        rescue NoMethodError
            puts "在程序中没有此方法,因此调用失败,因而抛出异常"
    
        rescue ArgumentError
            puts "在程序中传的参数不一致,因此会执行这一句"
    end
    
    #捕获系统异常
    p "-----------------------------------------"
    def myPro
        puts "这是我定义的myPro方法"
    end
    
    begin
        myPro "a","b"
    rescue Exception=>e
        puts "程序出现了异常"
        p "#{e.backtrace}"
        p "#{e.to_s}"
        p "#{e.message}"
    end
    
    #显示抛出异常
    def info
        raise NameError,"方法info显示抛出异常"
    end
    #info
    
    # 捕获抛出异常
    def info
        raise NameError,"方法info显示抛出异常"
    end
    
    begin
        info
    rescue NameError
            puts "捕获了NameError异常"
    end
    

5.10 正则表达式

  1. 正则表达式

    正则表达式 说明
    /a/ 匹配字符
    /?/ 匹配特殊字符。特殊字符包括 ^, &, ., /, , [, ], (, ), +, *
    . 匹配任意字符
    /[ab]c/ 匹配 ac 和 bc, []代表范围
    /[^a-zA-Z0-9]/ 匹配不在该范围之内的字符串
    /[\d]/ 代表任意数字
    /[\w]/ 代表任意字母,数字或者_
    /[\s]/ 代表空白符,包括空格、Tab和换行
    ? 代表0或1个字符
    * 代表0或多个字符
    + 代表1或多个字符
    /d{3}/ 匹配3个数字
    /d{1,10}/ 匹配1~10个数字
    /d{3, }/ 匹配3个数字以上
    /([A-Z]\d){5}/ 匹配首位是大写字母,后面4位是数字的字符串
  2. 匹配正则表达式 的方式

    • "=~" 和 ".match()"
    • "=~" 相对于 match ,如果有匹配的字符串会返回值的索引,否则返回 nil
    • match 如果有匹配的字符串时,返回true,否则返回 false
  3. 提取 匹配 的值

    • 可以通过使用小括号来指定获取的子字符串,然后将匹配的字符串保存
    # 正则表达式
    # match
    if /a-z/.match("dcy")
        puts "字符串 ‘dcy‘ 匹配上面的正则表达式"
    else
        puts "字符串 ’dcy’ 不匹配上面的正则表达式"
    end
    
    
    if "lws".match(/[a-z]/)
        puts "字符串 ‘lws’ 匹配上面的正则表达式"
    else
        puts "字符串 ‘lws’ 不匹配上面的正则表达式"
    end
    
    # =~
    p "Hello, Jack"=~/Hello*/
    p "Jack, Hello"=~/Hello*/
    
    # 提取 匹配的值
    reg=/([a-z]+),([A-Za-z]+)/
    str="abc,Dcy"
    reg.match(str)
    p "匹配的第一个小括号中的正则表达式是#{$1}"
    p "匹配的第二个小括号中的正则表达式是#{$2}"
    

5.11 时间和日期

  1. Time.new 获取当前时间

  2. Mktime 和 local 获取时间

    • 使用 mktime 和 local 创建时间对象时,需要传递参数从而形成一个新的Time对象
    • 传递参数顺序依次是: 年、月、日、时、分、秒、微妙,这里年对应的参数必须填写,其他的参数可选
  3. gm 方法获取时间

    • 它使用的是GMT和UTC时区
  4. 对时间对象进行操作

    • to_a 转化为数组操作

      下标 对应值
      0 秒(sec)
      1 分钟(min)
      2 小时(hour)
      3 日期(day/mday)
      4 月份(mon/month)
      5 年份(year)
      6 星期(wday)
      7 一年中的第几天(yday)
      8 是否为夏令时间(true 或者 false)
      �9 时区(zone)
    • yday、mday、wday 年月日中 第几天

    • 时间相加减: 在特定的时间上增加间隔 就可以获取新的时间 (间隔的单位为秒)

    • 两个Time 对象相减,就可以得到秒数

  5. 时间的格式化

    指令名称 说明
    %a 星期天数的缩写
    %A 完整的星期天数
    %b 月的名称的缩写
    %B 完整的月的名称
    %c 等价于%a%b%d%H%M%S%Y
    %d 一个月中的第几天(01~31)
    %e 一个月中第几天
    %H 以24小时制表示的时间(00~23)
    %I 以12小时制表示的时间(1~12)
    %m 月份(1~12)
    %M 分钟(00~59)
    %p AM或PM
    %S 秒(00-59)
    %w 一星期中的第几天
    %x 等价于“%m%d%y”

示例:

```
# 时间和日期
time=Time.new
p "当前的日期时间是:#{time}"
p "当前的年份是#{time.year}年"
p "当前的月份是#{time.month}月"
p "当前的日是#{time.day}日"
p "当前的小时是#{time.hour}小时"
p "当前的分钟时#{time.min}分钟"
p "当前的秒是#{time.sec}秒"
p "当前的微妙是#{time.usec}微妙"


for i in 1...10
    time=Time.new
    p "当前时间是#{time}"
#    sleep(1)
end


time=Time.gm(2020,4,1,16,20,20)
p "使用gm的方法创建的时间对象"+time.to_s


# 返回时间
p "--------分别返回的第几天--------"
time=Time.new
p "一年中的第#{time.yday}天"
p "一个月中的第#{time.mday}天"
p "一个星期中的第#{time.wday}天"


# 时间的间隔
p "----------计算相隔的时间-----------"
mkTime=Time.mktime(2020,4,1,16,20,45)
mkTime1=mkTime+60
mkTime2=mkTime+3600
mkTime3=Time.now-mkTime
p "现在和约定的时间相差:"+mkTime3.to_s+"秒"


#日期格式化
time=Time.now
p time.strftime("%Y年%m月%d日%H时%M分%S秒")
p time.strftime("今天是: %x")
p time.strftime("今天是%m月中的第%d天")
p time.strftime("今天是%B月%a———%A")
 ```

5.12 线程的创建及操作

  1. Ruby 中 线程是用户级 线程并依赖于操作系统。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程可与同属一个进程的其他线程共享进程拥有的全部资源,但进程并不拥有系统资源,它只需要一点在运行中必不可少的资源。

  2. 在Ruby中,创建线程只需要创建Thread的实例即可,同时为实例添加一个将作为线程体的块。

    xiancheng=Thread.new do
        #线程块
    end
    
  3. 线程 可以并发执行

  4. 线程创建除了 Thread.new 还有 Thread.startThread.fork

  5. 使用 current 方法来返回线程 Thread.current

  6. joinvalue 方法可以挂起当前线程,然后执行指定的线程。其中 value 还可以获得线程的值

  7. pass 显示,并执行其他可以执行的线程

  8. wakeup 把被挂起(stop)的线程的状态改为可执行状态(run), 若对死线程执行该方法时,将会引发ThreadError异常

  9. exitkill 可以停止当前线程。如果用exit 或者 kill 方法停止了主线程,相当于退出

  10. 使用 status 获取线程的状态

|线程状态|说明|
|:------:|:------:|
|sleep| 线程处于休眠状态,或者在等待IO|
|run| 线程处于运行状态|
|aborting| 线程被取消|
|false| 线程正常终止|
|nil| 线程被非正常终止|

本节示例:

```
# 创建线程
require "thread"
i=1
a=Thread.new 10 do |value|
    while i<value
        puts "#{i}"
        i=i+1
    end
end

b=Thread.new do
    10.times do |a|
        puts "第#{a+1}次输出"
    end
end
a.join
b.join

p "----------线程的创建及操作 ----------"

#start和fork 创建线程
thread=Thread.start "hello" do |value|
    puts "我是使用start方法来创建的线程+#{value}\n"
end

thread=Thread.fork "world" do |value|
    puts "我是使用fork方法来创建的线程+#{value}\n"
end
thread.join

p "----------------------------------------------------------------------------"
#返回当前线程
i=Thread.fork do
    currenThread=Thread.current
    p "使用start创建一个新的线程,当前的线程是:"+currenThread.to_s
end
i.join

mainThread=Thread.current
p "主线程是"+mainThread.to_s

p "----------------------------------------------------------------------------"
# join的使用
i=0
threadjoin1=Thread.new 10 do |value|
    while i<value
        puts "#{i}\n"
        p "#{i}\n"
        i=i+1
    end
end

threadjoin1.join
threadjoin2=Thread.new do
    10.times do |a|
        puts "第#{a+1}次输入"
    end
end
threadjoin2.join

p "----------------------------------------------------------------------------"
# pass 显示线程
threadpass1=Thread.start do
    Thread.pass
    puts "我没希望了,看你的了,加油happy! \n"
end

p=Thread.start do
    puts "看我的吧,我一定会成功的,因为我是happy\n"
end
threadpass1.join
p.join


p "----------------------------------------------------------------------------"
## wakeup 唤醒线程
#puts "开始的时间是:"+Time.new.to_s
#sleep 2
#puts "暂停两秒之后的时间是:"+Time.new.to_s
#
#puts "第二次开始的时间是:"+Time.new.to_s
#sleep 3
#puts "暂停三秒之后的时间是:"+Time.new.to_s

#线程的停止
i=1
threadkill1=Thread.new 10 do |value|
    while i<value
        puts "#{i}"
        i=i+1
        if (i>5)
            Thread.kill threadkill1
        end
    end
end

threadexit1=Thread.new do
    10.times do |a|
        puts "第#{a+1}次比赛"
        if (a>=4)
            Thread.exit
        end
    end
end

threadkill1.join
threadexit1.join
p "----------------------------------------------------------------------------"

# 线程的状态
threadpass1=Thread.start do
    puts "我是正常运行的\n"
end
s1=threadpass1.status
puts "我的状态是:"+s1.to_s
threadpass1.join
threadpass1.exit
s2=threadpass1.status
puts "我的状态是:"+s2.to_s
p "----------------------------------------------------------------------------"

# main
thread1=Thread.new do
    sleep 2
end

thread2=Thread.new do
    if Thread.current==Thread.main
        puts "当期的线程就是主线程"
    end
end
num=Thread.list.size
puts "线程的数量是:#{num}"
if Thread.list.include?(Thread.main)
    puts "现在运行的就是主线程"
end
```

5.13 同步线程

  1. 同步线程:
    同步线程,即使一组并发进程直接制约而互相发送消息从而进行互相合作,互相等待,使得各进程按一定的速度执行的过程称之为进程间的同步。由于线程共享内存空间,因此使用普通变量就可以进行数据间的交换工作。但是为了使操作的时机得当,需要对线程进行同步。

  2. Ruby 中的三种同步

    • 只负责同步的 Mutex 类中的方法
    • 兼管数据交接的 Queue 类中的方法
    • 使用 ConditionVariable 类实现同步
  3. 同步队列类

    • Queue 表示一个支持线程的队列,能狗同步队列末尾进行访问
    • SizedQueue 能够限制 队列的长度
    • ConditionVariable
    # 使用 lock 锁定资源
    @num=200
    @mutex=Mutex.new
    def ticketNum(num)
        @mutex.lock
        Thread.pass
        if (@num>=num)
            @num-=num
            puts "您已经成功购买#{num}张火车票"
        else
            puts "对不起,您购买的#{num}张火车票失败,已经没有了。"
        end
        @mutex.unlock
    end
    
    ticketsuccess=Thread.new(199){|num|ticketNum(num)}
    ticketsuccess1=Thread.new(2){|num|ticketNum(num)}
    ticketsuccess.join
    ticketsuccess1.join
    
    #使用try_lock 锁定资源
    mutex=Mutex.new
    thread=Thread.new do
        mutex.lock
        sleep 30
    end
    
    thread1=Thread.new do
        if mutex.try_lock
            puts "其他线程,没有占用,您老可以使用"
        else
            puts "它是我的,哈哈,不能被锁定"
        end
    end
    thread.join
    thread1.join
    
    # synchronize  锁定
    @num=200
    @mutex=Mutex.new
    def ticketNum(num)
        @mutex.synchronize do
            Thread.pass
            if (@num>=num)
                @num-=num
                puts "您已经成功购买#{num}张电影票"
            else
                puts "对不起,您购买的#{num}张电影票失败,已经没有了。"
            end
        end
    end
    
    ticketsuccess=Thread.new(199){|num|ticketNum(num)}
    ticketsuccess1=Thread.new(2){|num|ticketNum(num)}
    ticketsuccess.join
    ticketsuccess1.join
    
    #Queue 同步队列
    require 'thread'
    queueR=SizedQueue.new(25)
    maxSize=queueR.max
    puts "队列中最大的长度是:#{maxSize}"
    queueR.max=78
    maxSize=queueR.max
    puts "修改后的队列中最大的长度是:#{maxSize}"
    

第六章学习

6.1 访问文件属性

  1. 获取硬盘中文件的信息
  • File 类内嵌一个 stat 类,可以实现对文件属性的访问操作
  • File::Stat 类 配合 File 类来实现对文件属性的访问,包括文件操作权限,文件大小,文件时间戳等
  • File::Stat 类 并不是在所有操作系统上都能使用
  • File::Stat 类 Mode 实现方法可以获得对文件的访问权限, chmod 方法来修改文件的权限
  • FileTest 中 exist?exists? 来 检查文件是否存在
  • FileTest 中 size? 返回大小,如果为0,则为nil
  • FileTest 中 zero? 如果文件大小为0,返回ture;否则返回false
  • FileTest 中 size 返回文件的实际大小
  1. 获取与设置文件时间戳
  • File::Stat 类 mtimeatimectime 方法获取时间

  • File 类 utime 设置一个文件的最后访问时间和最后修改时间

    # 文件权限
    fp="../RubyFolder/0500第五章内容.rb"
    mode=File.stat(fp).mode  # 获取文件权限
    puts "该文件的访问权限代码为:#{mode}"
    File.chmod(01522, fp)       # 修改文件权限
    mode=File.stat(fp).mode   # 获取文件权限
    puts "修改以后该文件的访问权限代码为:#{mode}"
    
    
    # 检查文件是否存在
    fp="../0501第五章1.rb"
    exist=FileTest.exist?(fp)
    exists=FileTest.exists?(fp)
    if(exist)
        puts "exist:文件#{fp}存在"
    else
        puts "exist:文件#{fp}不存在"
    end
    
    if(exists)
        puts "exists:文件#{fp}存在"
    else
        puts "exists:文件#{fp}不存在"
    end
    
    fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/0501第五章1.rb"
    puts "size?="+FileTest.size?(fp).to_s
    puts "zero?="+FileTest.zero?(fp).to_s
    puts "size="+FileTest.size(fp).to_s
     
    # 获取修改访问时间
    fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/calc.rb"
    #使用File类的类方法获取三个时间戳
    mtime1=File.mtime(fp)
    atime1=File.atime(fp)
    ctime1=File.ctime(fp)
    #修改时间戳
    File.utime(Time.now,Time.now,fp)
    #使用File类的实例方法获取三个时间戳
    file=File.new(fp)
    mtime2=file.mtime
    atime2=file.atime
    ctime2=file.ctime
    puts "#{fp}文件的时间戳"
    puts "mtime=#{mtime1}"
    puts "atime=#{atime1}"
    puts "ctime=#{ctime1}"
    puts "#{fp}修改后的时间戳"
    puts "mtime=#{mtime2}"
    puts "atime=#{atime2}"
    puts "ctime=#{ctime2}"
    

6.2 读取文件

  1. 打开文件

    • 使用 File 类的 new 方法打开文件

      • 使用new 方法 创建 一个对象的时候,就已经打开了指定的文件(只能读取)
      • 第二个参数为可选参数,称之为模式字符串,它指定以何种方式打开文件,默认值为 r(read)
      模式字符串 说明
      r 以只读模式打开文件,同时将文件指针放在文件的开始处
      r+ 以读写模式打开文件,同时将文件指针放在文件的开始处
      w 以只写模式打开文件,打开文件时,会自动清空文件内容,然后再写入文件。如果打开文件不存在,则自动创建该文件
      w+ 以读写模式打开文件。再打开文件以后,清空文件内容才能写人文件。如果打开的文件不存在,则自动创建该文件
      a 以追加的模式打开该文件,并且将文件指针放在执行文件的结尾,以备向文件中写入内容。如果要打开的文件不存在,则自动创建该文件
      a+ 以读取/追加的模式打开文件,并且将文件指针放在文件结尾,以备读取文件或向文件中追加内容。如果要打开的文件不存在,则自动创建该文件
      b 以二进制的形式打开文件,这种方式只适合DOS平台或者Microsoft Windows 平台
  2. 使用File 类的 open 方法

    • Ruby 还可以使用File类中的一个open类方法来打开文件

    • 使用File类的 open 方法打开文件的使用方法和 new 方法相似

    • 使用 open 方法,可以给该方法传递一个代码块 作为参数,如果代码块调用open方法时,系统将会把文件对象传递给块,然后开始块的执行

      #open 打开代码
      fp="路径"
      File.open(fp) do |file|
          #file 参数即打开的文件对象
      end
      
  3. 使用 open 方法

    • 类似于File 类中的 open 方法,调用时传递 代码块,或返回一个对象文件

      fp="路径"
      file=open(fp)
      open(fp) do |file|
          #file变量是一个文件对象
      end
      
  4. 关闭文件

    • 操作文件后,需要关闭文件,使用 File 类的 close 方法关闭打开的文件

    • File 类中还提供了 close_read/close_write 方法,用于关闭只读模式打开文件和只写模式打开的文件

      fp="路径"
      file=open(fp)   #打开文件
              #对文件进行操作
      file.close  #关闭文件
      
  5. 读取文件

    • read、readchar、readline、readlines、gets 等

      • read 方法可以从文件对象中读取指定字节数的文本。如果指定字节数大于文件内容的长度,那么将读取到文件结尾。例如: read(length, buf)
      • 参数 length 是声明读取的文本长度,参数 buf 是用于保存读取出来的文本内容。参数buf是一个可选参数
    • 移动文件指针

      • pos 获取指针的位置
      • pos= 设置指针的位置
      • rewind 将文件指针移动到文件的开始位置
      • lineno 返回指针所在的行
      • lineno= 设置指针所在的行
    • readchar 方法

      • readchar 方法可以从文件对象中读取一个字符
    • readline 方法和 readlines 方法

      • readline 方法 可以从指定的文件中读取一行,不过当读到文件末尾时,会引发 EOFError 异常
      • readlines 方法 可以读取文件的所有行,并把所有行的内容保存在数组中,数组的每个元素都是文件的一行内容
    • 迭代文件中的行

      • Ruby 中的 File类提供了两个 对文件 进行 迭代读取的方法: each_line 和 each。这两个方法功能相同,都是依次将文件里的每一行传入代码块,进行迭代。
      • 按字节迭代: File 类 提供了以字节为单位迭代文件的方法,方法名为 each_byte
      • foreach 迭代器 迭代文件内容,其可以以行的形式迭代文件的内容
      # 打开文件
      fp="路径"
      file=File.new(fp)
      file=File.new(fp,"r")
      p file
      
      ##open 打开代码
      #fp="路径"
      #File.open(fp) do |file|
      #    #file 参数即打开的文件对象
      #end
      p '\n-------------------------------------\n'
      # 读取文件
      fp="路径"
      file=File.new(fp)
      puts file.read(19)
      b=""
      p '\n-------------------------------------\n'
      puts file.read(24, b)
      p '\n-------------------------------------\n'
      puts b
      p '\n-------------------------------------\n'
      puts file.read
      file.close
      
      
      #移动指针的位置
      fp="路径"
      file=File.new(fp)
      puts file.read(8)
      puts "指针所在的位置:#{file.pos}"
      file.pos=2
      puts file.read(8)
      puts "指针所在的位置:#{file.pos}"
      file.close
      
      # readchar 方法
      p '\n-------------------------------------\n'
      fp="路径"
      file=File.new(fp)
      puts file.readchar
      file.close
      
      p '\n-------------------------------------\n'
      #readline 方法 和 readlines 方法
      fp="路径"
      file=File.new(fp)
      while line=file.gets
          puts line
      end
      file.close
      
      
      # 迭代文件的行 each_line 和 each
      p '\n-------------------------------------\n'
      fp="路径"
      file=File.new(fp)
      file.each do |line|
          puts line
      end
      file.close
      
      p '\n-------------------------------------\n'
      # 以字节迭代 each_byte
      fp="路径"
      file=File.new(fp)
      file.each_byte do |b|
          print "#{b}"
      end
      puts
      file.close
      
      p '\n-------------------------------------\n'
      # foreach 迭代器
      fp="路径"
      IO.foreach(fp) do |line|
          print "#{line}"
      end
      puts
      

6.3 写入文件

  1. 写入文件
    • print、puts、putc、write方法

      • print方法 将一行或多行字符串写入文件,并且不换行。可以通过设置“$\” 来让每次写入之后增加换行
      • puts方法 将一行字符串或多行字符串写入一个文件,每次写入之后自动换行
      • putc方法 将一个字符写入一个文件。如果传入一个整数参数,则将该参数转换成字符后写入
      • write方法 将一行字符串写入一个文件
        • 在Ruby中,写入文件需要使用写入(w、w+) 或者追加(a、a+)模式打开一个文件。
    • 追加文件内容

      • 追加文件内容的时候需要讲文件使用“a” 模式打开该文件
      # 写入文件
      p '\n-------------------------------------\n'
      # 写入w
      fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/xieruFile.rb"
      file=File.new(fp,"w")
      $\="\n"    # 设置执行玩print 方法自动换行
      file.puts("静夜思")
      file.write("-——李白")
      file.puts("\n床前明月光")
      file.puts("疑是地上霜")
      file.print("举头望明月")
      file.print("低头思故乡")
      file.close
      
      # foreach 迭代器
      fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/xieruFile.rb"
      IO.foreach(fp) do |line|
          print "#{line}"
      end
      puts
      
      # 追加文件内容
      fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/xieruFile.rb"
      file=File.new(fp,"a")
      file.puts("诗评: 这是一首唐代大诗人李白的诗")
      file.close
      
      IO.foreach(fp) do |line|
          print "#{line}"
      end
      

6.4 操作文件

  1. 删除、重命名操作

    • 删除文件: File类中 delete 方法 和 unlink 方法
      • 用于删除普通文件,成功则返回删除个数,失败抛出 Errono::error 异常
    • 重命名文件: File类中,rename 方法
      • rename 方法 接收两个字符串做为参数,第一个字符串参数表示原文件名,另一个表示新文件名
      • 如果新名称不在同一个目录下,系统会自动将文件重命名并移动到新的目录
      • 如果移动中目录文件不存在,则会抛出异常,新指向的文件存在,则会自动覆盖
    # 删除文件
    fp="/路径/Delegate.rb"
    fd="/路径/Unlink.rb"
    puts File.unlink(fp)
    puts File.delete(fd)
    
    # 重命名
    fp1="/路径/renmae.rb"
    fp2="/路径/reName/renmae.rb"
    File.rename(fp1, fp2)
    

6.5 操作路径

  1. File 类 操作路径
  • dirname 和 basename
    * 根据这两个方法路径 获取 目录名称和文件名称
    * basename 方法可以设置第二个参数,第二个参数设置的是文件中要截取的后缀,如果第二个参数为文件的扩展名,则方法返回的将是不加扩展名的文件名称

    • expand_path 方法 (获取绝对路径)
    • 链接路径( join的类方法 )
      • 可以根据用方法调用者提供的字符串生成新的路径
    # 操作路径
    #扩展名
    fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/renmae.rb"
    puts File.dirname(fp)
    puts File.basename(fp)
    puts File.basename(fp, ".text")
    
    # expand_path 类方法 获取绝对路径
    fp="/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/renmae.rb"
    puts File.expand_path(fp)
    
    #链接路径
    puts File.join("study", "coder", "ruby", "file.txt")
    

6.6 操作目录

  1. 获取、改变、删除、遍历 目录

    • DIr 类 对目录的操作,进行 目录的遍历,修改,删除 操作
    • pwd 和 getwd 可以 获取当前目录
    • chdir 改变当前目录
      • 方法接收一个新目录路径为参数,执行完后将当前目录切换到新目录中
      • 如果没有为该方法设置参数,那么该方法将当前目录切换到当前系统用户所在的目录中
      • 如果该方法所指向的新目录不存在的话,将抛出一个Rrrno::ENOENT 异常
    • 遍历目录内容
      • foreach 和 each 方法来迭代目录内容
      • entries 类 可以直接以数组的形式 返回所有的目录内容
    • 删除指定目录
      • delete、rmdir、unlink 可以用于删除指定的目录
      • 删除成功,返回0;不存在 抛出Errno::ENOENT 异常; 目录不为空, 将抛出 Errno::ENOTEMPTY 异常
    #操作目录
    # 获取当前目录
    puts Dir.pwd
    puts Dir.getwd
    
    #改变当前目录
    puts "--------------------------------"
    puts Dir.pwd
    Dir.chdir("/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder")
    puts Dir.pwd
    Dir.chdir("/Users/apple/AllProject/PROJECT-AllDemo/Project-All-Data-Ruby/RubyFolder/rename")
    puts Dir.pwd
    Dir.chdir
    puts Dir.pwd
    
    # 遍历内容
    puts "#{Dir.pwd}目录中的内容:"
    Dir.foreach(Dir.pwd) do |item|
        puts item
    end
    puts "--------------------------------"
    d=Dir.new(Dir.pwd)
    d.each do |item|
        puts item
    end
    puts "----------------------------------"
    list=Dir.entries(Dir.pwd)
    list.each do |item|
        puts item
    end
    
    # 删除目录
    begin
        puts Dir.delete("aa")
        rescue Exception=>e
        puts e.class
    end
    begin
        puts Dir.rmdir("bb")
        rescue Exception=>e
        puts e.class
    end
    begin
        puts Dir.unlink("cc")
        rescue Exception=>e
        puts e.class
    end
    

相关文章

  • Ruby or Rails 学习总结 3

    Qo_Tn 第五章学习 5.1 模块的定义与使用 模块的定义模块和类相似,也是由一组方法和常量组成。对于类来说模块...

  • 2016-11-06 task-list

    今日任务 ruby on rails 第八章 ruby on rails 指南 今日总结 Action view ...

  • rails基础汇总

    一:ruby on rails, Router路由 前言:ruby学习掌握20%就可以开始rails的学习了,知道...

  • ROR高级开发工程(蛋人网)

    01 Ruby on Rails介绍02 Ruby on Rails快速上手03 Model基础学习04 Mode...

  • 2016-11-05 task-list

    今日任务 ruby on rails 第6章 ruby 元编程 第3章 总结 数据库迁移生成User模型 注意:控...

  • Ruby or Rails 学习总结 1

    Qo_Tn 第一章 学习 1.1 Ruby ruby 特性 弱类型 语言 1.3 下载安装Ruby 和 Rai...

  • Ruby or Rails 学习总结 2

    Qo_Tn 第三章学习 3.1 创建字符串 String:单引号或双引号 创建。单引号字符串 只能进行最少替换。双...

  • 实现Demo

    1、安装rails工具 在安装rails之前需要先安装Ruby和SQLite3.检查Ruby是否安装的方式是在命令...

  • You should use PG::Connection, P

    $ rails -v Rails 4.2.6 $ruby -v ruby 2.3.1 1.Gemfile -sou...

  • ruby on rails 安装报错“LZMA_OK”

    最近对ruby有了新的兴趣,既然学习ruby,当然rails不容错过。所以在安装rails 过程中遇到的问题,...

网友评论

    本文标题:Ruby or Rails 学习总结 3

    本文链接:https://www.haomeiwen.com/subject/cmgmuhtx.html