therubyway:ruby way的IO的一

  1 打开和关闭个文件

  类思路方法File. 打开个文件并将它例子化为个File对象个参数是文件名.

  可选第 2个参数叫做 mode (这个也是从c得来).他意思是怎样打开个文件(读写或者其他).默认是'r'(也就是读).

file1 = File.("one")    # Open for reading 
 
file2 = File.("two", "w") # Open for writing


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

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

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

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


  这里还有个open思路方法最简单形式是和同义:

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.("file1", "r+") 
# Read/write, starting at beginning of file. 
f2 = File.("file2", "w+") 
# Read/write; truncate existing file or create a  one. 
f3 = File.("file3", "a+") 
# Read/write; start at end of existing file or create a 
#  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.("myfile") 
file.seek(5) 
str = file.gets          # "fghi"


  如果你能确定每行都是固定长度你就能seek指定行:

# Assume 20 s per line. 
# Line N starts at  (N-1)*20 
file = File.("fixedlines") 
file.seek(5*20)          # Sixth line! 
# Elegance is left as an exercise.


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

file = File.("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 s from eof

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

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


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

  5 操作 2进制文件

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

  可是在windows下是例外在他下面 2进制文件和文本文件区别是在 2进制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  2进制模式结尾是个回车换行对. 
file.close


  binmode思路方法能够转换当前流为 2进制模式这边要注意旦切换过去就不能切换回来了:

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.("myfile",'a+') 
output = File.("outfile",'a+') 
instr = input.sysread(10); 
puts instr 
s = output.syswrite("This is a test.")


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

  这边要注意 Array pack和unpack思路方法对于处理 2进制数据非常有用.

  6 文件锁

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

file = File.("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 line 
putc("X")  # Output the letter X


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

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

diskfile = File.("foofile","w") 
puts "Hello..."   # prs to stdout 
$stdout = diskfile 
puts "Goodbye!"   # prs to "foofile" 
diskfile.close 
$stdout = STDOUT   # reassign to default 
File.open("foofile","r") do |file| 
 p file.gets 
end 
puts "That's all."  # prs 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般使用他自己内置缓冲:

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


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

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

pr "Hello... " 
STDOUT.flush 
sleep 10 
pr "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操作文件权限和所有权

  为了得到个文件权限和所有者我们能够是用Fileuid和gid思路方法:

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


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

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

  Filechown思路方法能够改变个文件拥有者和组id:

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


  chmod 思路方法能够改变个文件权限:

File.chmod(0644, "epsilon", "theta") 
f = File.("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所能理解时间戳分 3种,修改时间访问时间和改变时间.

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

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.("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")




Tags:  ruby安装 ruby是什么意思 rubyonrails therubyway

延伸阅读

最新评论

发表评论