FileTest exist?思路方法可以检测个文件是否存在:
flag = FileTest::exist?("LochNessMonster")
flag = FileTest::exists?("UFO")
# exists? is a synonym for exist?
如果我们想要知道文件是否有内容可以使用File::Statzero? 思路方法:
flag = File.("somefile").stat.zero?
这个将会返回true这是在ruby中0也是true,nil才是false.
所以我们可以使用size?思路方法:
File.("myfile").stat.size?
puts "The file has contents."
puts "The file is empty."
end
FileTest模块里面也有zero? 和size?思路方法:
flag1 = FileTest::zero?("file1")
flag2 = FileTest::size?("file2")
这里还有个size思路方法:
size1 = File.size("file1")
size2 = File.stat("file2").size
2 检测特殊文件属性
这边要注意File类mix了FIleTest模块并且FileTest模块和File::Stat模块功能上也有很多重复.
unix/linux有面向和面向块设备FileTest思路方法blockdev?和chardev?可以进行测试:
flag1 = FileTest::chardev?("/dev/hdisk0") # false
flag2 = FileTest::blockdev?("/dev/hdisk0") # true
有时我们想要知道个流是否联系到了终端这时我们可以使用IO类tty?思路方法:
flag1 = STDIN.tty? # true
flag2 = File.("diskfile").isatty # false
个流可以是个管道或者个:
flag1 = FileTest::pipe?(myfile)
flag2 = FileTest::?(myfile)
要区分目录和普通文件我们这样使用:
file1 = File.("/tmp")
file2 = File.("/tmp/myfile")
test1 = file1.directory? # true
test2 = file1.file? # false
test3 = file2.directory? # false
test4 = file2.file? # true
File还有个类思路方法ftype他将返回流类型.他也在File::Stat里面,只不过是例子思路方法.它返回值可能是下面
串(file、directory、blockSpecial、characterSpecial、fo、link或).
this_kind = File.ftype("/dev/hdisk0") # "blockSpecial"
that_kind = File.("/tmp").stat.ftype # "directory"
要测试个文件是否为另个文件链接可以使用FileTestsymlink?思路方法要计算链接数量可以使用nlink思路方法:
File.symlink("yourfile","myfile") # Make a link
is_sym = FileTest::symlink?("myfile") # true
hard_count = File.("myfile").stat.nlink # 0
3 使用管道
ruby中使用IO.popen打开管道:
check = IO.popen("spell","r+")
check.puts("'T was brillig, and the slithy toves")
check.puts("Did gyre and gimble in the wabe.")
check.close_write
list = check.readlines
list.collect! { |x| x.chomp }
# list is now %w[brillig gimble gyre slithy toves wabe]
要注意 必须close_write,如果没有它读取管道时候就不能到达文件末尾.
下面是个block形式:
File.popen("/usr/games/fortune") do |pipe|
quote = pipe.gets
puts quote
# On a clean disk, you can seek forever. - Thomas Steel
end
如果指定了个串"-"那么个新ruby例子将被创建.如果指定了个block那么这个block将会作为两个独立
进程运行子进程得到nil父进程得到个IO对象:
IO.popen("-") do |mypipe|
mypipe
puts "I'm the parent: pid = #{Process.pid}"
listen = mypipe.gets
puts listen
puts "I'm the child: pid = #{Process.pid}"
end
end
# Prs:
# I'm the parent: pid = 10580
# I'm the child: pid = 10582
pipe思路方法也返回互相连接对管道:
pipe = IO.pipe
reader = pipe[0]
writer = pipe[1]
str = nil
thread1 = Thread.(reader,writer) do |reader,writer|
# writer.close_write
str = reader.gets
reader.close
end
thread2 = Thread.(reader,writer) do |reader,writer|
# reader.close_read
writer.puts("What hath God wrought?")
writer.close
end
thread1.join
thread2.join
puts str # What hath God wrought?
4 使用非阻塞IO
ruby会在后台执行些操作使io不会被阻断因此大部分情况下可以使用ruby线程来管理IO,当个线程被Io阻塞的
后另外线程能够继续执行.
由于ruby线程不是个native线程因此ruby线程都在同个进程里面.
如果你想关闭个非阻塞io你可以这样做:
require 'io/nonblock'
# ...
test = mysock.nonblock? # false
mysock.nonblock = true # turn off blocking
# ...
mysock.nonblock = false # turn on again
mysock.nonblock { some_operation(mysock) }
# Perform some_operation with nonblocking to true
mysock.nonblock(false) { other_operation(mysock) }
# Perform other_operation with non-blocking to false
5 使用readpartial
readpartial被设计来用于就像这样流.
readpartial要求提供最大长度参数如果指定了buffer那么这个buffer应指向用于存储数据个串
data = sock.readpartial(128) # Read at most 128 s
readpartial 思路方法不能接受非阻塞flag,他有时会阻塞:IO对象buffer是空;流内容为空;流没有到达文件末尾
因此如果流中还有数据话readpartial将不会阻塞.
如果流没有数据并且他已经抵达文件末尾readpartial 将会立即抛出个EOFError.
如果阻塞他将会等待直到接收到数据或者得到个EOF.
当sysread 在阻塞模式下他行为和readpartial相似.
6 操作路径名
先来看下File.dirname和File.basename思路方法:
str = "/home/dave/podbay.rb"
dir = File.dirname(str) # "/home/dave"
file1 = File.basename(str) # "podbay.rb"
file2 = File.basename(str,".rb") # "podbay"
File.split思路方法可以将个文件路径名和文件名分隔开:
info = File.split(str) # ["/home/dave","podbay.rb"]
类思路方法expand_path 将个相对路径转换为个绝对路径名:
Dir.chdir("/home/poole/personal/docs")
abs = File.expand_path("../../misc") # "/home/poole/misc"
对于打开文件path 将会返回这个文件路径名:
file = File.("../../foobar")
name = file.path # "../../foobar"
类思路方法类思路方法join正好和split相反:
path = File.join("usr","local","bin","someprog")
7使用Pathname
pathname类实际上是,Dir, File, FileTest,和FileUtils包装器它包含他们很多功能:
require 'pathname'
path = Pathname.("home/hal")
file = Pathname.("file.txt")
p2 = path + file
path.directory? # true
path.file? # false
p2.directory? # false
p2.file? # true
puts parts = p2.split # [Pathname:/home/hal, Pathname:file.txt]
puts ext = p2.extname # .txt
再看看其他有用思路方法:
p1 = Pathname.("//") # odd but legal
p1.root? # true
p2 = Pathname.("/home/poole")
p3 = p2.parent # Pathname:/home
items = p2.children # .gif' /> of Pathnames (all files and
# dirs immediately under poole)
relative和absolute判断路径是否是相对:
p1 = Pathname.("/home/dave")
p1.absolute? # true
p1.relative? # false
8 Command-Level 文件操作
其实也就是copy, delete, rename,等等 些操作了:
File.delete("history")
File.unlink("toast")
File.rename("Ceylon","SriLanka")
File.link("/etc/hosts","/etc/hostfile") # hard link
File.symlink("/etc/hosts","/tmp/hosts") # symbolic link
File.truncate("myfile",1000) # Now at most 1000 s
fileUtils也有很多有用思路方法
require "fileutils"
same = FileUtils.compare_file("alpha","beta") # true
# Copy epsilon to theta and log any errors.
FileUtils.copy("epsilon","theta", true)
FileUtils.move("/tmp/names","/etc") # Move to directory
FileUtils.move("colours","colors") # Just a rename
FileUtils.safe_unlink("alpha","beta","gamma")
# Log errors on the next two files
FileUtils.safe_unlink("delta","epsilon",true)
FileUtils.("foo.so","/usr/lib")
9 从键盘抓取输入
也就是抓取用户从键盘输入
unix平台:
def getchar
system("stty raw -echo") # Raw mode, no echo
char = STDIN.getc
system("stty -raw echo") # Re terminal mode
char
end
windows平台:
require 'Win32API'
def getchar
char = Win32API.("crtdll", "_getch", , 'L').Call
end
10 读取整个文件到内存
读取整个文件到你不需要打开文件IO.readlines 可以完成这个工作他自己会open和close.
arr = IO.readlines("myfile")
lines = arr.size
puts "myfile has #{lines} lines in it."
longest = arr.collect {|x| x.length}.max
puts "The longest line in it has #{longest} characters."
也可以用IO.read(它返回个大串):
str = IO.read("myfile")
s = arr.size
puts "myfile has #{s} s in it."
longest = str.collect {|x| x.length}.max # s are enumerable!
puts "The longest line in it has #{longest} characters."
由于File继承了IO,因此File也有这两个思路方法.
11 逐行迭代个文件
我们可以使用IO.foreach 思路方法或者each思路方法如果是前者文件不需要显示打开:
# Pr all lines containing the word "target"
IO.foreach("somefile") do |line|
puts line line =~ /target/
end
# Another way...
file = File.("somefile")
file.each do |line|
puts line line =~ /target/
end
12逐字节对文件进行遍历
可以使用each_思路方法如果你想要转换到话使用chr思路方法:
file = File.("myfile")
e_count = 0
file.each_ do ||
e_count 1 ?e
end
12 把串当文件来用
我们可以使用io库:
require 'io'
ios = StringIO.("abcdefghijkl\nABC\n123")
ios.seek(5)
ios.puts("xyz")
puts ios.tell # 8
puts ios..dump # "abcdexyzijkl\nABC\n123"
c = ios.getc
puts "c = #{c}" # c = 105
ios.ungetc(?w)
puts ios..dump # "abcdexyzwjkl\nABC\n123"
puts "Ptr = #{ios.tell}"
s1 = ios.gets # "wjkl"
s2 = ios.gets # "ABC"
13读取嵌套在中数据
ruby中末尾__END__ 标记介绍说明下面数据是内嵌数据你可以使用个IO对象DATA来读取
# Pr each line backwards...
DATA.each_line do |line|
puts line.reverse
end
__END__
A man, a plan, a canal... Panama!
Madam, I'm Adam.
,siht daer nac uoy fI
.drah oot gnikrow neeb ev'uoy
14 读取源码
DATA指向__END__ 后面数据如果你rewind,它将会将文件指针指向开头:
DATA.rewind
num = 1
DATA.each_line do |line|
puts "#{'%03d' % num} #{line}"
num 1
end
__END__
15 操作临时文件
这里使用Tempfile库:
require "tempfile"
temp = Tempfile.("stuff")
name = temp.path # "/tmp/stuff17060.0"
temp.puts "Kilroy was here"
temp.close
# Later...
temp.open
str = temp.gets # "Kilroy was here"
temp.close(true) # 立即删除
16 改变和设置当前目录
得到当前目录可以使用Dir.pwd或他别名Dir.getwd来获得.
Dir.chdir 用来改变当前目录:
Dir.chdir("/var/tmp")
puts Dir.pwd # "/var/tmp"
puts Dir.getwd # "/var/tmp"
这个还能接受个block,接受block介绍说明block里代码都是在改变了目录下进行:
Dir.chdir("/home")
Dir.chdir("/tmp") do
puts Dir.pwd # /tmp
# other code...
end
puts Dir.pwd # /home
17改变当前根目录
Dir.chdir("/home/guy/sandbox/tmp")
Dir.chroot("/home/guy/sandbox")
puts Dir.pwd # "/tmp"
18 遍历个目录
Dir.foreach("/tmp") { |entry| puts entry }
dir = Dir.("/tmp")
dir.each { |entry| puts entry }
19 创建个目录链
在linux使用mkdir -p来做在ruby中我么可以这么做:
require "fileutils"
FileUtils.makedirs("/tmp/these/dirs/need/not/exist")
20 递归删除目录
在linux下我们能够使用rm -rf ...来做,在ruby中我们能这么做:
require 'pathname'
dir = Pathname.("/home/poole/")
dir.rmtree
# or:
require 'fileutils'
FileUtils.rm_r("/home/poole")
21 查找文件和目录
使用find库来做:
require "find"
def findfiles(dir, name)
list =
Find.find(dir) do |path|
Find.prune [".",".."].? path
name
when String
list << path File.basename(path) name
when Regexp
list << path File.basename(path) =~ name
raise ArgumentError
end
end
list
end
findfiles "/home/hal", "toc.txt"
# ["/home/hal/docs/toc.txt", "/home/hal/misc/toc.txt"]
findfiles "/home", /^[a-z]+.doc/
# ["/home/hal/docs/alpha.doc", "/home/guy/guide.doc",
# "/home/bill/help/readme.doc"]
最新评论