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

ruby way之IO之一

    博客分类:
  • ruby
阅读更多
1 打开和关闭一个文件
类方法File.new 打开一个文件,并将它实例化为一个File对象,他的第一个参数是文件名.

可选的第二个参数叫做 mode string(这个也是从c得来的).他的意思是怎样打开一个文件(读,写或者其他的).默认是'r'(也就是读).
file1 = File.new("one")       # Open for reading

file2 = File.new("two", "w")  # Open for writing


另外一种new的形式是三个参数的,其中第二个参数是指定了这个文件的原始的权限(经常表示为一个八进制的数).第三个参数是一系列Ored标志的组合.标志是个常量比如File:CREAT(如果文件不存在则创建它)和File:RDONLY(以只读方式打开文件)。不过这种形式很少使用:

file = File.new("three", 0755, File::CREAT|File::WRONLY)


出于对操作系统和运行环境的考虑,如果你打开了一个文件的话,你就必须关闭它。当你打开一个文件用于写时,你更应该这样做,从而才能免于丢失数据.close方法就是关闭一个文件:

out = File.new("captains.log", "w")
# Process as needed...
out.close

这里还有一个open方法,它的最简单的形式是和new同义的:
trans = File.open("transactions","w")


但是open方法还能够带一个block作为参数,当存在block时,打开的文件将会做为一个参数传递给block.这时这个文件将会在这个block的作用域里,保持打开,直到block结束时,自动关闭:

File.open("somefile","w") do |file|
  file.puts "Line 1"
  file.puts "Line 2"
  file.puts "Third and final line"
end


2 更新文件

假设我们想要打开一个文件用于读和写,简单的加一个'+'号到file mode就行了:
f1 = File.new("file1", "r+")
# Read/write, starting at beginning of file.
f2 = File.new("file2", "w+")
# Read/write; truncate existing file or create a new one.
f3 = File.new("file3", "a+")
# Read/write; start at end of existing file or create a
# new one.


3 追加一个文件

假设我们想要追加一段信息到一个存在文件,当我们打开文件时使用'a'作为file mode就行了:

logfile = File.open("captains_log", "a")
# Add a line at the end, then close.
logfile.puts "Stardate 47824.1: Our show has been canceled."
logfile.close


4随机存取一个文件

如果你想随即存取一个文件,你能够使用seek方法,它是File从Io继承而来的.它的最简单的使用就是指定一个字节位置.这个位置是相对于文件开始的位置(开始的位置是0):
# myfile contains only: abcdefghi
file = File.new("myfile")
file.seek(5)
str = file.gets                   # "fghi"


如果你能确定每一行都是固定的长度,你就能seek指定的行:
# Assume 20 bytes per line.
# Line N starts at byte (N-1)*20
file = File.new("fixedlines")
file.seek(5*20)                   # Sixth line!
# Elegance is left as an exercise.


如果你想做一个相对的搜索,你就要使用第二个参数,常量 IO::SEEK_CUR表示当前的位置,而第一个参数则就是相对于当前位置的偏移量(可能是负数):

file = File.new("somefile")
file.seek(55)                 # Position is 55
file.seek(-22, IO::SEEK_CUR)  # Position is 33
file.seek(47, IO::SEEK_CUR)   # Position is 80


你也能从文件的结束位置开始搜索:

file.seek(-20, IO::SEEK_END)  # twenty bytes from eof


方法tell得到文件的当前位置,pos是它的别名:

file.seek(20)
pos1 = file.tell             # 20
file.seek(50, IO::SEEK_CUR)
pos2 = file.pos              # 70


rewind方法将会将文件指针的位置设回到开始的位置,也就是0.

5 操作二进制文件

在很久以前,c语言通过在file mode后附加一个'b'来表示将文件用二进制模式打开.在今天,二进制文件的处理已经没有那么麻烦了。在ruby中,一个字符串很容易保存一个二进制数据,而且也不用通过任何特殊的方式来读文件.

可是在windows下是例外,在他下面,二进制文件和文本文件的不同是,在二进制mode下,结束行不能被转义为一个单独的换行,而是被保存为一个回车换行对.
另外的不同是,在文本模式下 control-Z被作为文件的结束:

# Create a file (in binary mode)
File.open("myfile","wb") {|f| f.syswrite("12345\0326789\r") }
# Above note the embedded octal 032 (^Z)
# Read it as binary
str = nil

File.open("myfile","rb") {|f| str = f.sysread(15) }
puts str.size           # 11
# Read it as text
str = nil
File.open("myfile","r") {|f| str = f.sysread(15) }
puts str.size           # 5


这边注意,这些代码都是在windows下才会打印出后面的结果,如果是在linux两处都会打印出11.
再看下面的代码:
# Input file contains a single line: Line 1.
file = File.open("data")
line = file.readline             # "Line 1.\n"
puts "#{line.size} characters."  # 8 characters
file.close
file = File.open("data","rb")
line = file.readline             # "Line 1.\r\n"
puts "#{line.size} characters."  # 9 characters 二进制模式的结尾是一个回车换行对.
file.close


binmode方法能够转换当前的流为二进制模式,这边要注意的是,一旦切换过去,就不能切换回来了:
file = File.open("data")
file.binmode
line = file.readline             # "Line 1.\r\n"
puts "#{line.size} characters."  # 9 characters
file.close


如果你想使用更底层的输入输出,那你可以选择sysread和syswrite方法,他们接受一定数量的字节作为参数 .
input = File.new("myfile",'a+')
output = File.new("outfile",'a+')
instr = input.sysread(10);
puts instr
bytes = output.syswrite("This is a test.")


如果文件指针已经到达文件的结尾时,sysread方法将会抛出一个异常.

这边要注意 Array 的pack和string的unpack方法,对于处理二进制数据非常有用.

6 文件锁

操作系统提供文件锁,File的flock方法将会锁或者解锁一个文件,它的参数是下面的实例中的任意一个. File::LOCK_EX, File::LOCK_NB, File::LOCK_SH, File::LOCK_UN,或者用逻辑操作符or来组合这些实例.

file = File.new("somefile")
file.flock(File::LOCK_EX)  # 排他锁; 一个时刻只能有一个进程获得锁。
file.flock(File::LOCK_UN)  # 现在解锁。
file.flock(File::LOCK_SH)  #共享锁,一个时刻,可以有多个进程获得给定文件的锁。
file.flock(File::LOCK_UN)  # 解锁
locked = file.flock(File::LOCK_EX | File::LOCK_NB)
#lock_nb表示加锁时不阻塞,因此这边将会返回false 


7 执行简单的io

你已经很熟悉kernel模块中的一些io方法,这些方法都是没有接收者的。比如gets,puts,还有p.

除了上面我们已经说过的那些方法,还有几个方法需要记住的。putc方法输出一个单独的字符,如果给定字符串,将字符串的第一个字符将会被输出:

putc(?\n)   # Output a newline
putc("X")   # Output the letter X


这边有一个问题,这些方法都没有接收者,那么他们的输出去那里了?在ruby中对应于unix的三个标准io流也有三个常量,他们分别是,STDIN, STDOUT,和 STDERR。他们是类型IO的全局变量.

这边还有一个全局变量叫做 $stdout,它是kernel中的所有输出方法的目的地, $stdout能够随时被指向其他的一些io对象:

diskfile = File.new("foofile","w")
puts "Hello..."      # prints to stdout
$stdout = diskfile
puts "Goodbye!"      # prints to "foofile"
diskfile.close
$stdout = STDOUT     # reassign to default
File.open("foofile","r") do |file|
	p file.gets
end
puts "That's all."   # prints to stdout


除了gets方法,kernel还有readline和readlines方法用于输入.readline的格式和gets相似,除了在文件结尾时,它会返回一个 EOFError ,而gets则是返回nil. readlines方法则是相当于 IO.readlines.

输入是从那儿来的呢?这里有一个标准的输入流 $stdin,默认是 STDIN.同样的这里还有一个错误流($stderr defaulting to STDERR).

这里还有一个全局变量ARGF,它表示一连串的命令行所有文件名,他不是一个真正的file对象:

# Read all files, then output again
puts ARGF.read  
# Or more memory-efficient:如果想要使用这个模式,则需要将上面的代码注释掉.
while ! ARGF.eof?
  puts ARGF.readline
end
# Example:  ruby cat.rb file1 file2 file3


从标准输入读取将会绕过ARGF方法:
# Read a line from standard input
str1 =  STDIN.gets
# Read a line from ARGF
str2 = ARGF.gets #将会什么也读不到
# Now read again from standard input
str3 =  STDIN.gets


8 执行缓冲和非缓冲的IO

ruby一般使用他自己内置的缓冲:

print "Hello... "
sleep 10
print "Goodbye!\n"


如果你运行这个程序,你将会注意到hello,和Goodbye!\n在sleep之后同时打印到屏幕,而且Hello...后面并没有换行符.

我们这时可以使用flush方法来来刷新缓冲区,在这里我们使用 $defout作为接收者:

print "Hello... "
STDOUT.flush
sleep 10
print "Goodbye!\n


sync= 方法可以关闭缓冲,sync则可以返回此时的是否有缓冲:
buf_flag = $defout.sync    # true
STDOUT.sync = false
buf_flag = STDOUT.sync     # false


这里还有一个更底层的缓冲操作,getc方法返回一个字符,ungetc则将一个字符压回流:
ch = mystream.getc    # ?A
mystream.ungetc(?C)
ch = mystream.getc    # ?C


这里注意,这个缓冲和上面所说的并不一样,比如sync= false并不能关掉上面的缓冲。ungetc将不能在比如sysread方法里使用,因为sysread是一个没有缓冲的读操作.

9操作文件的权限和所有权

为了得到一个文件的权限和所有者,我们能够是用File的uid和gid方法:

data = File.stat("somefile")
owner_id = data.uid
group_id = data.gid


类File::Stat 有一个实力方法mode,它返回文件的权限:

perms = File.stat("somefile").mode


File的chown方法能够改变一个文件的拥有者和组id:

uid = 201
gid = 10
File.chown(uid, gid, "alpha", "beta")
f1 = File.new("delta")
f1.chown(uid, gid)
f2 = File.new("gamma")
f2.chown(nil, gid)      # Keep original owner id


chmod 方法能够改变一个文件的权限:

File.chmod(0644, "epsilon", "theta")
f = File.new("eta")
f.chmod(0444)


我们经常需要知道某个文件,我们是否有读或者写的权限,我们可以使用File::Stat类的一些实例方法:

info = File.stat("/tmp/secrets")
rflag = info.readable?
wflag = info.writable?
xflag = info.executable?


有时我们需要区分有效的用户id,和实际的用户id,我们可以使用readable_real?, writable_real?, 和 executable_real?:
info = File.stat("/tmp/secrets")
rflag2 = info.readable_real?
wflag2 = info.writable_real?
xflag2 = info.executable_real?


可以通过比较当前进程的有效用户ID(和组ID)来测试文件的所有权,File::Stat类有实例方法 owned?和grpowned?

注意这些方法,很多在FileTest里面也有:

 
rflag = FileTest::readable?("pentagon_files")
    # Other methods are: writable? executable? readable_real?
writable_real?
    # executable_real? owned? grpowned?
    # Not found here: uid gid mode


和进程联系在一起的umask方法决定了一个新的文件的初始权限.(unmask的具体含义去网上搜索搜索就有了).

可以通过File的类方法unmask方法来获取umask。如果指定一个参数,则umask将会被设置为这个,并且将会返回原来的umask:

File.umask(0237)             # Set the umask
current_umask = File.umask   # 0237


10 得到和设置时间戳信息

ruby所能理解的时间戳分三种,修改时间,访问时间和改变时间.

mtime, atime和ctim分别返回这三种时间:

t1 = File.mtime("somefile")
# Thu Jan 04 09:03:10 GMT-6:00 2001
t2 = File.atime("somefile")
# Tue Jan 09 10:03:34 GMT-6:00 2001
t3 = File.ctime("somefile")
# Sun Nov 26 23:48:32 GMT-6:00 2000


如果正好创建了file实例或者File:;Stat实例,则可以使用实例方法:
myfile = File.new("somefile")
t1 = myfile.mtime
t2 = myfile.atime
t3 = myfile.ctime

info = myfile.stat

t1 = info.mtime

t2 = info.atime

t3 = info.ctime


文件的访问和修改时间能够通过utime来修改:
today = Time.now
yesterday = today - 86400
File.utime(today, today, "alpha")
File.utime(today, yesterday, "beta", "gamma")


由于他是同时改变两个时间,因此如果你想只改变一个的话,就要先保存:

mtime = File.mtime("delta")

File.utime(Time.now, mtime, "delta")



5
0
分享到:
评论

相关推荐

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

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

    The Ruby Way(第2版)

    The Ruby Way(第2版) <br>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(中文版)(第二版)pdf

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

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

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

    the ruby way 2ed

    《The Ruby Way 2nd Edition》是一本深入探讨Ruby编程语言的经典著作,旨在帮助读者全面理解和掌握Ruby的精髓。这本书的第二版在2006年出版,由Addison-Wesley出版,作者通过深入浅出的方式,揭示了Ruby语言的强大...

    the-ruby-way

    the ruby way the ruby way

    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

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

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

    the ruby way

    3. **块、 Proc 和 Lambda**:Ruby中的块(blocks)、Proc对象和Lambda表达式是其强大的功能之一,它们允许程序员创建闭包和匿名函数,用于处理迭代和回调。 4. **元编程**:Ruby的元编程能力强大,允许在运行时...

    11.5 时间日期the ruby way.rar

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

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

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

    Ruby-Way.rar_About Language

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

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

    通过以上内容的详细讲解,《The Ruby Way》第二版为读者提供了全面且深入的Ruby编程知识体系,无论是对于初学者还是有经验的开发者而言,都是一本非常有价值的参考书籍。此外,读者还可以从作者提供的网站...

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

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

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

    计算机的主要功能之一就是处理数据,这不仅包括内部计算,还包括输入输出(I/O)操作,即与外部世界的交互。Ruby作为一种现代的编程语言,为用户提供了一套强大且灵活的方式来处理文件和目录。下面将详细介绍Ruby中...

Global site tag (gtag.js) - Google Analytics