Qo_Tn
第五章学习
5.1 模块的定义与使用
-
模块的定义
模块和类相似,也是由一组方法和常量组成。
对于类来说模块没有实例,但可以将模块的功能添加到类或特定的对象中。 -
定义模块
关键字 module 、includemodule 方法名 模块体 end
-
混含操作
类中可以包含多个模块,但是类不能继承多个类 -
模块实现命名空间
所谓命名空间,就是一种将程序库名称封装起来的方法,它就像在各个程序库中立起一道道围墙。如果在同一个命名空间里面出现相同的方法名,编译就会出现错误。例如:
# 模块的创建与使用 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块
-
BEGIN 块 和 END块
- 类似于开始,结束
BEGIN{ 初始化代码块 } END{ 释放的代码块 }
-
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 加载其他文件
-
加载其他文件 (require、load)
-
load 和 require 加载其他文件
-
load 功能强大,除Ruby源文件外,还可以加载其他语言源文件
-
require 语法
require "源文件" require "源文件全名"
-
require 方法可以重复使用,但只能加载一次。而 load 方法却可以加载多次。
-
-
调用内部文件(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 别名和定义
-
alias 或 alias_method : 为方法或者全局变量添加别名。�
- 给方法添加别名时,别名方法和原始方法是绑定的。即使重新定义了原始方法,别名方法仍保持着重定之前的老方法的特性
-
定义的操作(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 的使用
-
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 特性
- 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对象
---------- 难点 -----------
-
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方法
-
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 异常处理机制
-
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 -
begin...end 块处理异常 resure 捕获
-
Ruby 中 的异常主要依赖于rescue 和 ensure 来完成,但是两者的任务�是不同的,rescue块主要是将程序从异常中解救出来,而ensure主要用于保证系统的资源回收
-
捕获 系统异常
rescue异常类=>实例名
-
获取异常常用的方法主要有
backtrace方法、创建实例的new方法 以及to_s 和 message方法
-
显示异常 及 捕获异常
#异常处理 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 正则表达式
-
正则表达式
正则表达式 说明 /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位是数字的字符串 -
匹配正则表达式 的方式
- "=~" 和 ".match()"
- "=~" 相对于 match ,如果有匹配的字符串会返回值的索引,否则返回 nil
- match 如果有匹配的字符串时,返回true,否则返回 false
-
提取 匹配 的值
- 可以通过使用小括号来指定获取的子字符串,然后将匹配的字符串保存
# 正则表达式 # 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 时间和日期
-
Time.new 获取当前时间
-
Mktime 和 local 获取时间
- 使用 mktime 和 local 创建时间对象时,需要传递参数从而形成一个新的Time对象
- 传递参数顺序依次是: 年、月、日、时、分、秒、微妙,这里年对应的参数必须填写,其他的参数可选
-
gm 方法获取时间
- 它使用的是GMT和UTC时区
-
对时间对象进行操作
-
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 对象相减,就可以得到秒数
-
-
时间的格式化
指令名称 说明 %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 线程的创建及操作
-
Ruby 中 线程是用户级 线程并依赖于操作系统。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。线程可与同属一个进程的其他线程共享进程拥有的全部资源,但进程并不拥有系统资源,它只需要一点在运行中必不可少的资源。
-
在Ruby中,创建线程只需要创建Thread的实例即可,同时为实例添加一个将作为线程体的块。
xiancheng=Thread.new do #线程块 end
-
线程 可以并发执行
-
线程创建除了
Thread.new
还有Thread.start
和Thread.fork
-
使用
current
方法来返回线程Thread.current
-
join
和value
方法可以挂起当前线程,然后执行指定的线程。其中value
还可以获得线程的值 -
pass
显示,并执行其他可以执行的线程 -
wakeup
把被挂起(stop)的线程的状态改为可执行状态(run), 若对死线程执行该方法时,将会引发ThreadError异常 -
exit
和kill
可以停止当前线程。如果用exit 或者 kill 方法停止了主线程,相当于退出 -
使用
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 同步线程
-
同步线程:
同步线程,即使一组并发进程直接制约而互相发送消息从而进行互相合作,互相等待,使得各进程按一定的速度执行的过程称之为进程间的同步。由于线程共享内存空间,因此使用普通变量就可以进行数据间的交换工作。但是为了使操作的时机得当,需要对线程进行同步。 -
Ruby 中的三种同步
- 只负责同步的 Mutex 类中的方法
- 兼管数据交接的 Queue 类中的方法
- 使用 ConditionVariable 类实现同步
-
同步队列类
- 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 访问文件属性
- 获取硬盘中文件的信息
- 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
返回文件的实际大小
- 获取与设置文件时间戳
-
File::Stat 类
mtime
、atime
和ctime
方法获取时间 -
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 读取文件
-
打开文件
-
使用 File 类的 new 方法打开文件
- 使用new 方法 创建 一个对象的时候,就已经打开了指定的文件(只能读取)
- 第二个参数为可选参数,称之为模式字符串,它指定以何种方式打开文件,默认值为 r(read)
模式字符串 说明 r 以只读模式打开文件,同时将文件指针放在文件的开始处 r+ 以读写模式打开文件,同时将文件指针放在文件的开始处 w 以只写模式打开文件,打开文件时,会自动清空文件内容,然后再写入文件。如果打开文件不存在,则自动创建该文件 w+ 以读写模式打开文件。再打开文件以后,清空文件内容才能写人文件。如果打开的文件不存在,则自动创建该文件 a 以追加的模式打开该文件,并且将文件指针放在执行文件的结尾,以备向文件中写入内容。如果要打开的文件不存在,则自动创建该文件 a+ 以读取/追加的模式打开文件,并且将文件指针放在文件结尾,以备读取文件或向文件中追加内容。如果要打开的文件不存在,则自动创建该文件 b 以二进制的形式打开文件,这种方式只适合DOS平台或者Microsoft Windows 平台
-
-
使用File 类的 open 方法
-
Ruby 还可以使用File类中的一个open类方法来打开文件
-
使用File类的 open 方法打开文件的使用方法和 new 方法相似
-
使用 open 方法,可以给该方法传递一个代码块 作为参数,如果代码块调用open方法时,系统将会把文件对象传递给块,然后开始块的执行
#open 打开代码 fp="路径" File.open(fp) do |file| #file 参数即打开的文件对象 end
-
-
使用 open 方法
-
类似于File 类中的 open 方法,调用时传递 代码块,或返回一个对象文件
fp="路径" file=open(fp) open(fp) do |file| #file变量是一个文件对象 end
-
-
关闭文件
-
操作文件后,需要关闭文件,使用 File 类的 close 方法关闭打开的文件
-
File 类中还提供了 close_read/close_write 方法,用于关闭只读模式打开文件和只写模式打开的文件
fp="路径" file=open(fp) #打开文件 #对文件进行操作 file.close #关闭文件
-
-
读取文件
-
read、readchar、readline、readlines、gets 等
- read 方法可以从文件对象中读取指定字节数的文本。如果指定字节数大于文件内容的长度,那么将读取到文件结尾。例如:
read(length, buf)
- 参数 length 是声明读取的文本长度,参数 buf 是用于保存读取出来的文本内容。参数buf是一个可选参数
- read 方法可以从文件对象中读取指定字节数的文本。如果指定字节数大于文件内容的长度,那么将读取到文件结尾。例如:
-
移动文件指针
- 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 写入文件
- 写入文件
-
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 操作文件
-
删除、重命名操作
- 删除文件: 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)
- 删除文件: File类中 delete 方法 和 unlink 方法
6.5 操作路径
- 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 操作目录
-
获取、改变、删除、遍历 目录
- 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
网友评论