在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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
puts str # What hath God wrought?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 4 使用非阻塞IO ruby会在后台执行一些操作,使io不会被阻断,因此大部分情况下可以使用ruby线程来管理IO,当一个线程被Io阻塞之 后,另外的线程能够继续执行. 由于ruby的线程不是一个native的线程,因此ruby的线程都在同一个进程里面. 如果你想关闭一个非阻塞io,你可以这样做: 代码:
require 'io/nonblock'
5 使用readpartial# ... 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 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("http://www.cnblogs.com/misc") # "/home/poole/misc" 对于打开的文件,path 将会返回这个文件的路径名: 代码:
file = File.new("http://www.cnblogs.com/foobar")
name = file.path # "http://www.cnblogs.com/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
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论