文件和输入输出(一)
一、文件对象(文件操作符或者文件句柄)
文件对象不仅可以访问普通的磁盘文件,也可以访问任何其他类型抽象层面上的“文件。
一旦设置了合适的“钩子”,你就可以访问具有文件类型接口的其他对象,就好像访问的是普通文件一样。
内建函数open()返回一个文件对象,对该文件进行的后续操作都要用到它。还有大量的函数也会返回文件对象或是类文件(file-like)对象。
进行这种抽象处理的主要原因是许多的输入/输出数据结构更趋向于使用通用的接口。这样可以在程序行为和实现上保持一致。
请记住,文件只是连续的字节序列,数据的传输经常会用到字节流,无论字节流是由单个字节还是大块数据组成。
二、文件内建函数(open())
作为打开文件之门的“钥匙”,内建函数open()提供了初始化输入/输出(I/O)操作的通用接口。
open()内建函数成功打开一个文件后会返回一个文件对象,否则引发一个错误。
file_object = open(file_name,access_mode='r',buffering=-1 )
file_name:要打开的文件名字字符串,它可以是相对路径或者绝对路径。
access_mode:文件打开的模式。文件使用模式‘r’、‘w’或是‘a’模式来打开,分别代表读取、写入和追加。还有个“U”,代表通用换行符支持。
‘+’代表可读可写,‘b’代表二进制模式访问。
对于linux系统来说,‘b’是可有可无的,因为它们把所有的文件当成二进制文件,包括文本文件。
buffering:指示访问文件所采用的缓冲方式。其中0表示不缓冲,1表示只缓冲一行数据。
任何其他大于1的值代表使用给定给定值作为缓冲区,不提供该参数或者给定负值代表使用系统默认缓冲机制。
文件模式 | 操 作 |
r | 以读方式打开,文件必须已经存在 |
rU或U | 以读方式打开,同时提供通用换行符支持。 |
w | 以写方式打开,如果文件存在则清空。 |
a | 以追加模式打开,写入的数据追加到文件末尾 |
r+ | 以可读可写模式打开,如果先读后写,末尾追加;如果先写后读,首行覆盖,非常容易乱码 |
w+ | 以可写可读模式打开,尽管可读,文件直接被清空,如果想要读,那么要移动光标 |
a+ | 以读写模式打开 |
rb | 以二进制读模式打开 |
wb | 以二进制写模式打开 |
ab | 以二进制追加模式打开 |
rb+ | 以二进制读写模式打开 |
wb+ | 以二进制读写模式打开 |
ab+ | 以二进制读写模式打开 |
使用的较多的是:r、w、a、rb、wb、ab
当使用“U”标志打开文件的时候,所有的行分隔符都会被替换为分隔符。
open()打开文件依赖操作系统的提供的途径。
操作系统都有自己的编码,linux默认为utf-8,win默认gbk。所以跨系统时注意编码。
open()在打开文件的时候默认使用操作系统的编码。
路径前面加上r表示取消所有换行转义功能。
三、文件内建方法
open()成功执行并返回一个文件对象之后,所有对该文件的后续操作都将通过这个“句柄进行。
文件方法可以分为四类:输入、输出、文件内移动以及杂项操作。
1、输入
read():直接读取字符到字符串中,最多读取给定数目个字节。如果没有给定size参数(默认值为-1)或者size值为负,文件将被读取至末尾。
r:按字符读,rb:按字节读
缺点:占内存
f =open('123','r') print(f.read()) abc #一次打印所有内容 哈哈哈
readline():都去打开文件的一行,包括行结束符,作为字符串返回。
和read()相同,也有一个可选参数,默认为-1,代表读至行结束符。如果提供了该参数,那么在超过size字节后不会返回完整的行。
缺点:不知道到什么位置,文件结束
f =open('123','r') print(f.readline()) print(f.readline()) abc #一次打印一行 哈哈哈
readlines():读取所有(剩余)行然后把它们作为一个字符串列表返回。
f =open('123','r') print(f.readlines()) ['abc\n', '哈哈哈']
readable():判断文件是否可读
f =open('123','r') print(f.readable()) True #返回一个布尔值
注意:当使用输入方法如read()或readlines()从文件中读取行时,python并不会删除行结束符,这个操作留给了程序员。
类似的,输出方法write()或者writelines()也不会自动加入行结束符,你应该向文件写入数据前自己完成。
还有两者方法也是类似的。
read(num):读取指定字符数
f =open('456','r') print(f.read(5)) abcde
还有一种使用迭代来实现,使用的也是非常普遍。
f = open('练习') for line in f: print(line) f.close() apple 10 3 tesla100000 1 mac 3000 2 lenovo 30000 3
2、输出
write():把含有文件数据或二进制数据块的字符串写入到文件中去。
writelines():接受一个字符串列表作为参数,将它们写入文件。
writeable():判断文件是否可写
3、文件内移动
seek():可以在文件中移动文件指针到不同的位置,按照字节来计数。有三种模式,分别为0、1、2。0代表从头开始,2代表移动到末尾,2表示当前位置。
f = open('练习','r+') # f.write('\nabcdefgh\n') print(f.read()) print(f.tell()) print(f.read()) #这个read没有打印,因为指针 f.close() 结果: 12345678 10
seek()一般不常用,因为容易造成乱码。
4、其他
close():关闭文件来结束对它的访问。python垃圾收集机制也会在文件对象的引用计数降至零时自动关闭文件。
如果不显示的将文件关闭,那么你可能丢失输出缓冲区的数据。
fileno():返回打开文件的描述符。
flush():会直接把内部缓冲区中的数据立刻写入文件,而不是被动的等待输出缓冲区被写入。
isatty():是一个布尔内建函数,当文件是一个类tty设备时返回True,否则返回False。
trubcate():将文件截取到当前文件指针位置或者到给定size,以字节为单位。
truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果
12345678 abcdefgh #原字符串 f = open('练习','a+') f.truncate(10) f.close() 12345678 #为啥只有8个,win的换行符为\r\n,故而有两个字节
del :主动释放了一个python程序内存中的变量。
5、文件方法杂项
先看两个例子:
filename = input('enter file name: ') f = open(filename,'r') allLines = f.readlines() f.close() for eachLine in allLines: print(eachLine) 上面这段代码读完所有的行才开始向屏幕输出,处理大文件时,有些不便。 filename = input('enter file name: ') f = open(filename,'r') for eachLine in f: print(eachLine) f.close() 使用文件迭代器,每次只读取和显示一行
再看一个例子
import os filename = input("Enter file name:" ) fobj = open(filename,'w',encoding='utf-8') while True: aLine = input("Enter a line('.' to quit):") if aLine != ".": fobj.write('%s%s' % (aLine, os.linesep)), else: break fobj.close()
还有一些需要注意:
操作系统间的差异之一是它们所支持的分隔符不同。Linux使用\n,而win支持\r\n。
print语句默认在输出内容末尾后加一个换行符,在语句后加一个逗号就可以避免。
readline()和readlines()函数不对行里的空白字符做任何处理,所以你必须加上逗号。
如果你省略逗号,那么显示出的文本每行后会有两个换行符。一个是默认添加,一个是print自动添加。
文件路径:如果文件路径和所处的路径相同,那么就可以直接使用绝对路径。
如果文件路径和所处的路径不同,那么就必须使用绝对路径。
取消转义有两种方式:\\和r