1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 #Author:sking 4 """ 5 test_file.txt 6 文件内容如下: 7 打印字符串第一个字符 8 9 打印字符串第二个字符 10 """ 11 #打开文件test_file.txt 12 f = open('test_file.txt', 'r+') #f是文件的文件句柄,它是在内存中的,是内存中的一个对象 13 data = f.read() 14 print(data) 15 """ 16 data结果: 17 打印字符串第一个字符 18 19 打印字符串第二个字符 20 """ 21 data2 = f.read() #再读一次文件 22 print("data2=", data2) #data2= 23 # 此时的结果是data2= ,也就是此时读取的data2为空,为什么? 24 # 因为第一次data读的时候文件光标是从头开始一直读到最后的,再次读的时候, 25 # 是从此时光标所在的位置(此时光标在最后面)开始读取,因为光标已经在最后了, 26 # 后面已经没有任何内容了,当然data2就读不出来数据了 27 # 可以用seek重新定位光标的位置 28 f.seek(0) #将光标定位到文件的开始位置 29 data3 = f.read() 30 print(data3) 31 """ 32 data3结果: 33 打印字符串第一个字符 34 35 打印字符串第二个字符 36 """ 37 #写文件write 38 #f = open('test_file.txt', 'w') #如果是'w'写的模式的时候,系统会自动创建一个这个名字的文件, 39 # 如果该目录下有这个名字的文件,系统会直接覆盖掉原来的文件,原来的文件及内容就不存在了,所以这点一定要注意。 40 #f.write('\n\n写入字符串第三个字符') 41 f.seek(0) #seekable()判断文件内容是否可以进行seek操作,因为有些文件是不可以进行seek的 42 data4 = f.read() 43 print(data4) 44 f.close() 45 """ 46 打印字符串第一个字符 47 48 打印字符串第二个字符 49 50 写入字符串第三个字符 51 """ 52 #向文件追加内容 53 f = open('test_file.txt', 'a') #'a'是append 追加,但是不能读取文件 54 f.write('\n\nhaha') 55 print(f.readable()) #False 判断文件是否可读 56 f.close() 57 #读取一行内容 58 f = open('test_file.txt', 'r') 59 data = f.readline() 60 print(data) # 打印字符串第一个字符 61 #读取多行 62 data2 = f.readlines() 63 print(data2) 64 65 66 #读取到第3行 67 for index, line in enumerate(f.readlines()): #仅适合读取小文件 68 print(line.strip()) 69 if index == 2: 70 break; 71 f.close() 72 #读取大文件(推荐使用) 73 f = open('test_file.txt', 'r') 74 for line in f: #这样写的效果就是逐行读取文件中的内容,并且内存中始终仅保存读取的这一行内容 此时的f是一个迭代器 75 print(line) 76 f.close() 77 #查看文件游标所在的位置 78 f = open('test_file.txt', 'r') 79 print(f.tell()) #0 80 print(f.read(5)) 81 print(f.tell()) #10 因为一个汉字占2个字节,所以这里显示的是10 82 f.close() 83 f2 = open('test_file2.txt', 'r') 84 print(f2.tell()) #0 85 print(f2.read(5)) 86 print(f2.tell()) #5 因为一个英文占1个字节,所以这里显示的是5 87 f2.close() 88 89 90 f = open('test_file.txt', 'r+') 91 print(f.encoding) #cp936 #查看文件编码 92 print(f.name) # test_file.txt 查看文件名 93 94 #实时存储数据 95 #f.write("sdfadf") #因为代码执行的过程中并不是出现依据写到硬盘的代码就立马开始向硬盘存储。 96 #系统有一个阀门限制,系统会在内存中开辟一块用来临时存储的区域,当临时存储区域的数据达到一定值时,才会从内存存到硬盘上。 97 #所以并不是执行一行写的代码后,硬盘就一定已经保存了该结果,很可能该结果还没有被保存。 98 f.flush() 99 print(f.flush()) #None 100 101 f.close() 102 103 #截断字符truncate 104 f = open('test_file.txt', 'r+') 105 f.truncate(10) #打印字符串 从文件头开始截取10个字节(一个汉字是2个字节) 106 f.truncate() #如果什么都不写,就是截取0个字节也就相当于清空文件内容 107 f.close() 108 109 #写二进制文件内容 110 f = open('test_file.txt', 'wb') 111 f.write('hello'.encode(encoding='utf-8')) 112 f.close() 113 114 #演示进度条 115 import sys 116 import time 117 for i in range(31): 118 sys.stdout.write('#') 119 sys.stdout.flush() 120 time.sleep(0.3) 121 122 123 """ 124 一、文件操作 125 1.文件处理的流程 126 127 128 1)打开文件,得到文件句柄并赋值给一个变量 129 130 2)通过句柄对文件进行操作 131 132 3)关闭文件 133 134 例如: 135 136 f = open('chenli.txt') #打开文件 137 first_line = f.readline() 138 print('first line:',first_line) #读一行 139 data = f.read()# 读取剩下的所有内容,文件大时不要用 140 print(data) #打印读取内容 141 f.close() #关闭文件 142 143 144 2.文件操作基本用法 145 1)基本用法: 146 147 file_object = open(file_name, access_mode = ‘r’, buffering = -1) 148 149 open函数有很多的参数,常用的是file_name,mode和encoding 150 151 file_name:打开的文件名,若非当前路径,需指出具体路径 152 access_mode文件打开模式 153 buffering的可取值有0,1,>1三个,0代表buffer关闭(只适用于二进制模式),1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小; 154 encoding表示的是返回的数据采用何种编码,一般采用utf8或者gbk; 155 156 157 158 159 2)文件打开模式 160 161 r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】 162 w,只写模式【不可读;不存在则创建;存在则清空内容】 163 x, 只写模式【不可读;不存在则创建,存在则报错】 164 a, 追加模式【不可读文件,不存在则创建;存在则只追加内容】,文件指针自动移到文件尾。 165 "+" 表示可以同时读写某个文件 166 167 r+, 读写【可读,可写】 168 w+,写读【可读,可写】,消除文件内容,然后以读写方式打开文件。 169 x+ ,写读【可读,可写】 170 a+, 写读【可读,可写】,以读写方式打开文件,并把文件指针移到文件尾。 171 "b"表示以字节的方式操作,以二进制模式打开文件,而不是以文本模式。 172 173 174 175 rb 或 r+b 176 wb 或 w+b 177 xb 或 w+b 178 ab 或 a+b 179 注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 180 181 182 183 3)以读r的方式打开文件 184 185 186 187 #!/usr/bin/env python 188 # -*- coding:utf-8 -*- 189 f=open('1.txt',encoding='utf-8',mode='r') 190 print(f) 191 data1=f.read() 192 print(data1) 193 194 195 1.txt 196 197 55542342 198 123 199 输出: 200 201 <_io.TextIOWrapper name='1.txt' mode='r' encoding='utf-8'> 202 55542342 203 123 204 205 206 补充: 207 208 复制代码 209 1)python中有三个方法来处理文件内容的读取: 210 read() #一次读取全部的文件内容。返回字符串 211 212 readline() #每次读取文件的一行。 213 214 readlines() #读取文件的所有行,返回一个字符串列表。 215 216 2)print(f.readable()) #判断文件是否是r模式打开的 217 218 3)print(f.closed) #判断文件是否是关闭状态 219 220 4)python中在文本文件内容移动的操作 221 file.seek(offset,whence=0) #从文件中给移动指针,从whence(0起始,1当前,2末尾)偏移offset个字节,正往结束方向移动,负往开始方向移动 222 file.tell() #返回当前文件中的位置。获得文件指针位置 223 224 5) file.truncate(size=file.tell()) #截取文件到最大size个字节,默认为当前文件位置 225 复制代码 226 4)以w方式写入文件 227 228 复制代码 229 f=open('a.txt','w',encoding='utf-8') 230 # f=open('b.txt','r',encoding='utf-8') #以读的方式打开文件,文件不存在则报错 231 f=open('b.txt','w',encoding='utf-8') 232 # print(f.writable()) 233 234 f.write('111111\n22222222') 235 f.seek(0) 236 f.write('\n333333\n444444') 237 238 f.writelines(['\n55555\n','6666\n','77777\n']) 239 f.close() 240 复制代码 241 a.txt 为空 242 243 b.txt 244 245 333333 246 444444 247 55555 248 6666 249 77777 250 251 252 补充: 253 254 file.write(str) #向文件中写入字符串(文本或二进制) 255 file.writelines(seq) #写入多行,向文件中写入一个字符串列表,注意,要自己加入每行的换行符 256 file.flush() #刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入. 257 258 259 5)文件修改 260 261 复制代码 262 #!/usr/bin/env python 263 # -*- coding:utf-8 -*- 264 import os 265 read_f=open('b.txt','r') 266 write_f=open('.b.txt.swap','w') 267 for line in read_f.readlines(): 268 if line.startswith('1111'): 269 line='2222222222\n' 270 write_f.write(line) 271 read_f.close() 272 write_f.close() 273 os.remove('b.txt') 274 os.rename('.b.txt.swap','b.txt') 275 复制代码 276 277 278 3.上下文管理with语句 279 当你做文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。 280 281 正常情况下,代码如下: 282 283 file = open("/tmp/foo.txt") 284 data = file.read() 285 file.close() 286 这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。 287 288 然而with可以很好的处理上下文环境产生的异常。下面是with版本的代码: 289 290 with open("/tmp /foo.txt") as file: 291 data = file.read() 292 with的基本思想是with所求值的对象必须有一个__enter__()方法,一个__exit__()方法。紧跟with后面的语句被求值后,返回对象的__enter__()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的__exit__()方法。 293 294 295 296 补充: 297 298 模拟 tail -f access.log 299 300 复制代码 301 #!/usr/bin/env python 302 # -*- coding:utf-8 -*- 303 304 # tail -f access.log 305 import time 306 with open('access.log','r',encoding='utf-8') as f: 307 f.seek(0,2) 308 while True: 309 line=f.readline().strip() 310 if line: 311 print('新增一行日志',line) 312 time.sleep(0.5) 313 复制代码 314 315 316 """ 317 """ 318 read(),readline(),readlines()的区别 319 320 假设a.txt的内容如下所示: 321 123 322 Hello 323 Welcome 324 What is the fuck... 325 326 一、read([size])方法 327 328 read([size])方法从文件当前位置起读取size个字节,若无参数size, 329 则表示读取至文件结束为止,它范围为字符串对象 330 f = open("a.txt") 331 lines = f.read() 332 print(lines) 333 print(type(lines)) 334 f.close() 335 336 输出结果: 337 Hello 338 Welcome 339 What is the fuck... 340 <type 'str'> #字符串类型 341 342 二、readline()方法 343 344 从字面意思可以看出,该方法每次读出一行内容,所以,读取时占用内存小,比较适合大文件,该方法返回一个字符串对象。 345 346 f = open("a.txt") 347 line = f.readline() 348 print(type(line)) 349 while line: 350 print line, 351 line = f.readline() 352 f.close() 353 354 输出结果: 355 356 <type 'str'> 357 Hello 358 Welcome 359 What is the fuck... 360 361 三、readlines()方法读取整个文件所有行,保存在一个列表(list)变量中,每行作为一个元素,但读取大文件会比较占内存。 362 363 f = open("a.txt") 364 lines = f.readlines() 365 print(type(lines)) 366 for line in lines: 367 print (line) 368 f.close() 369 370 输出结果: 371 <type 'list'> 372 Hello 373 Welcome 374 What is the fuck... 375 376 四、linecache模块 377 378 当然,有特殊需求还可以用linecache模块,比如你要输出某个文件的第n行: 379 380 # 输出第2行 381 text = linecache.getline(‘a.txt',2) 382 print text, 383 384 对于大文件效率还可以。 385 """