ruby way之IO之一

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")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警中心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥中心基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值