`
simohayha
  • 浏览: 1403191 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

ruby way之Io之二

    博客分类:
  • ruby
阅读更多
1 检测文件是否存在及其大小

FileTest的 exist?方法可以检测一个文件是否存在:

flag = FileTest::exist?("LochNessMonster")
flag = FileTest::exists?("UFO")
# exists? is a synonym for exist?


如果我们想要知道文件是否有内容,可以使用File::Stat的zero? 方法:

flag = File.new("somefile").stat.zero?


这个将会返回true,这是因为在ruby中0也是true,nil才是false.

所以我们可以使用size?方法:

if File.new("myfile").stat.size?
  puts "The file has contents."
else
  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.new("diskfile").isatty  # false


一个流可以是一个管道,或者一个socket:

flag1 = FileTest::pipe?(myfile)
flag2 = FileTest::socket?(myfile)


要区分目录和普通文件我们这样使用:

file1 = File.new("/tmp")
file2 = File.new("/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、fifo、link或socket).

this_kind = File.ftype("/dev/hdisk0")     # "blockSpecial"
that_kind = File.new("/tmp").stat.ftype   # "directory"


要测试一个文件是否为另一个文件的链接,可以使用FileTest的symlink?方法,要计算链接数量,可以使用nlink方法:

File.symlink("yourfile","myfile")           # Make a link
is_sym = FileTest::symlink?("myfile")       # true
hard_count = File.new("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|
  if mypipe
    puts "I'm the parent: pid = #{Process.pid}"
    listen = mypipe.gets
    puts listen
  else
    puts "I'm the child: pid = #{Process.pid}"
  end
end

# Prints:
#   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.new(reader,writer) do |reader,writer|
  # writer.close_write
  str = reader.gets
  reader.close
end

thread2 = Thread.new(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 set to true

mysock.nonblock(false) { other_operation(mysock) }
# Perform other_operation with non-blocking set to false


5 使用readpartial

readpartial被设计来用于就像socket这样的流.

readpartial要求提供最大长度的参数,如果指定了buffer,那么这个buffer应指向用于存储数据的一个字符串。

data = sock.readpartial(128)  # Read at most 128 bytes


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.new("../../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.new("home/hal")
file = Pathname.new("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.new("//")           # odd but legal
p1.root?                          # true
p2 = Pathname.new("/home/poole")
p3 = p2.parent                    # Pathname:/home
items = p2.children               # array of Pathnames (all files and
                                  # dirs immediately under poole)


relative和absolute判断路径是否是相对的:

p1 = Pathname.new("/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 bytes


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 new 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.install("foo.so","/usr/lib")


9 从键盘抓取输入

也就是抓取用户从键盘输入的字符。
unix平台:

def getchar
  system("stty raw -echo")  # Raw mode, no echo
  char = STDIN.getc
  system("stty -raw echo")  # Reset terminal mode
  char
end


windows平台:

require 'Win32API'

def getchar
  char = Win32API.new("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")
bytes = arr.size
puts "myfile has #{bytes} bytes in it."

longest = str.collect {|x| x.length}.max     # strings are enumerable!
puts "The longest line in it has #{longest} characters."


由于File继承了IO,因此File也有这两个方法.

11 逐行迭代一个文件

我们可以使用IO.foreach 方法,或者each方法,如果是前者文件不需要显示打开:

# Print all lines containing the word "target"
IO.foreach("somefile") do |line|
  puts line if line =~ /target/
end

# Another way...
file = File.new("somefile")
file.each do |line|
  puts line if line =~ /target/
end


12逐字节对文件进行遍历

可以使用each_byte方法,如果你想要转换byte到字符的话使用chr方法:

file = File.new("myfile")
e_count = 0
file.each_byte do |byte|
  e_count += 1 if byte == ?e
end


12 把字符串当文件来用

我们可以使用stringio库:

require 'stringio'

ios = StringIO.new("abcdefghijkl\nABC\n123")

ios.seek(5)
ios.puts("xyz")

puts ios.tell             # 8

puts ios.string.dump      # "abcdexyzijkl\nABC\n123"

c = ios.getc
puts "c = #{c}"           # c = 105

ios.ungetc(?w)

puts ios.string.dump      # "abcdexyzwjkl\nABC\n123"

puts "Ptr = #{ios.tell}"

s1 = ios.gets             # "wjkl"
s2 = ios.gets             # "ABC"


13读取嵌套在程序中的数据

ruby中程序末尾的__END__ 标记说明,下面的数据是程序内嵌的数据,你可以使用一个IO对象DATA来读取。

# Print 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.new("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.new("/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.new("/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 if [".",".."].include? path
    case name
      when String
        list << path if File.basename(path) == name
      when Regexp
        list << path if File.basename(path) =~ name
    else
      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"]
































4
0
分享到:
评论

相关推荐

    The Ruby Way(第2版)

    The Ruby Way(第2版) &lt;br&gt;The Ruby Way assumes that the reader is already familiar with the subject matter. Using many code samples it focuses on "how-to use Ruby" for specific applications, either ...

    The Ruby Way--3rd Edition--2015-英文版

    The Ruby Way 第三版(英文版),全书22章,书中包含600多个按主题分类的示例。每个示例都回答了“如何使用Ruby来完成”的问题。 ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!

    THE RUBY WAY(中文版)(第二版)pdf

    《The Ruby Way 第二版》...“《The Ruby Way (第2版)中文版》在阐述元编程(metaprogramming)等方面尤其出类拔萃,而元编程是Ruby最引人注目的方面之一。” ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!

    the ruby way 2ed

    这本书的第二版在2006年出版,由Addison-Wesley出版,作者通过深入浅出的方式,揭示了Ruby语言的强大功能和优雅特性。 Ruby是一种动态类型、面向对象的编程语言,它的设计理念是注重简洁和生产力,让开发者能够更...

    ruby学习资源(Programming Ruby, Learning Ruby, The Ruby Way)

    内含以下4个文档: 1、Addison.Wesley.The.Ruby.Way.2nd.Edition.Oct.2006.chm 2、O'Reilly.Learning.Ruby.May.2007.chm 3、Programming Ruby 2e.pdf 4、ruby中文文档.chm

    stream-ruby, ruby 客户端生成活动使用 GetStream.io 提供&流.zip

    stream-ruby, ruby 客户端生成活动使用 GetStream.io 提供&流 流 ruby 是一款用于构建可以伸缩新闻发布和活动流的web服务的官方 ruby 客户端,它是流。注意,还有一个更高级的 Ruby on Rails - 流集成插件库,它将...

    the-ruby-way

    the ruby way the ruby way

    rubywork ruby编程例子 逻辑 IO 数据库

    rubywork ruby编程例子 逻辑 IO 数据库rubywork ruby编程例子 逻辑 IO 数据库 rubywork ruby编程例子 逻辑 IO 数据库rubywork ruby编程例子 逻辑 IO 数据库rubywork ruby编程例子 逻辑 IO 数据库

    the ruby way

    《The Ruby Way》第二版是Addison-Wesley出版社在2006年10月出版的一本关于Ruby编程语言的权威指南。这本书深入浅出地介绍了Ruby语言的核心特性和高级用法,旨在帮助读者全面理解和掌握Ruby的精髓。通过阅读这本书,...

    Addison Wesley The Ruby Way 2Nd Edition Oct 2006.pdf(英文版)

    ### Addison Wesley《The Ruby Way》第二版(2006年10月) #### 书籍概览 《The Ruby Way》是由Hal Fulton编写的关于Ruby编程语言的经典著作,该书的第二版出版于2006年10月,由Addison Wesley Professional出版社...

    cool.io, ruby的简单主题 I/O ( 但请检查赛车).zip

    cool.io, ruby的简单主题 I/O ( 但请检查赛车) Cool.io如果你对基于赛璐珞的IO框架感兴趣,...Cool.io 是 ruby的事件库,构建在libev事件库之上,它提供了一个跨平台接口,用于高性能。 这包括Linux的epoll系统调用,bs

    11.5 时间日期the ruby way.rar

    "11.5 时间日期the ruby way"这个主题深入探讨了Ruby中处理时间日期的最佳实践和常见用法。让我们逐一了解这些知识点。 首先,`Time.now`是Ruby中获取当前时间的标准方法。它返回一个`Time`对象,表示自1970年1月1...

    Ruby-Way.rar_About Language

    《Ruby Way》是由Hal Fulton编写的关于Ruby编程语言的一本著作。这本书深入浅出地探讨了Ruby语言的各种特性,旨在帮助读者理解并掌握这门强大的动态脚本语言。Ruby以其简洁、优雅的语法和强大的元编程能力而备受赞誉...

    Ruby-Async是基于nio4r和定时器的Ruby的可组合的异步IO框架

    Ruby-Async是建立在这个理念之上,通过nio4r库来实现对多种I/O事件的监听。nio4r是一个用于非阻塞I/O操作的高性能库,它基于Java的NIO(非阻塞I/O)接口,为Ruby提供了类似的功能。nio4r提供了一种高效的方式来注册...

    The Ruby Way(处理文件和目录)

    它继承自`IO`类,这意味着所有`IO`类提供的功能都可以在`File`类中使用。通过`File.new`方法可以创建并打开一个文件对象,该方法接收文件名作为第一个参数。 **模式字符串**: 可以通过指定第二个参数来设置文件的...

Global site tag (gtag.js) - Google Analytics