Python文件处理

Stella981
• 阅读 866

Python文件处理

Python文件处理

在python中,要对一个文件进行操作,得把文件抽象为Streams或者说file object或者叫file-like objects
这样将文件当作一个流对象来处理就方便多了。Stream对象提供了很多操作方法(如read(),write()等),操作这些Stream对象就是操作文件对象。所以python的概念里,文件对象即Stream。主要想说明的是:文件在python中都抽象成了Stream。
Stream是简介操作I/O,所以要准许各种类型I/O设备各自的操作。操作Stream不是代表I/O的数据全部存在内存中,而是通过Stream操作I/O。

note1:python中这三种叫法是一样的:File object/Stream/File-like objects
note2:除了文件会抽象成为Stream,依据不同的创建Stream的方式,可分为磁盘文件or其它类型存储中的文件or通信设备(通信设备中如:stdin/stdout,sockets,in-memery buffers,pipes等),这些都可以通过它们自己独特的方式抽象为Stream,然后都可以通过Stream的接口像操作文件一样间接操作这些可以读写i/o的实体

官方文档:

The io module provides Python’s main facilities for dealing with various types of I/O. There are three main types of I/O: text I/O, binary I/O and raw I/O. These are generic categories, and various backing stores can be used for each of them. A concrete object belonging to any of these categories is called a file object. Other common terms are stream and file-like object.

怎么将文件变为python中的file-object文件对象?

对于磁盘文件这类io实体,python是通过内置函数open()进行创建

file_oject = open( r'测试文件.txt', 'r') # 通过open得到文件对象

file_contents = file_object.read() # 操作文件对象的方法read,读取文件中内容。通常我们把这种通过间接的对象去操作实体对象的对象叫handle句柄.就像遥控板和电视机关系。

if file_contents:

print(file_contents)

文件对象提供哪些操作呢?读、写、改?

上面open操作我们看到,除了提供文件路径,还有第二个参数。这个参数是文件打开的模式。通过指定不同的模式,就限制了文件对象的读写行为。下表说明不同模式的意思:

character

meaning

‘r’

open for reading(default)

‘w’

open for writing,truncating the file first

‘a’

open for writing,appending to the end of the file if it exists

‘x’

open for exclusive creation,writing,non-reading,failing if the file already exists

‘b’

binary mode

‘t’

text mode(default)

‘+’

open a disk file for updating (reading and writing)

‘U’

univeral newlines mode(deprecated弃用;不赞成)

除去’U’模式,其它模式还可以分为3类,前四个都是打开操作一类,’b’ 和’t’是决定是二进制还是文本一类。有’+‘和没’+‘ 又是一类是否可读写。三类组合下,就有16种组合模式,每种组合模式有自己的特点和其返回的对象所能支持的操作。

从两个角度来说明什么限制了文件对象能支持的操作:

  1. 就是上面提到的打开模式限制。
  2. 文件对象类型决定了其支持的操作(虽然第一中情况也部分决定了返回的file object对象类型,但是肯定存在其它方式创建file object的)。

Independently of its category, each concrete stream object will also have various capabilities: it can be read-only, write-only, or read-write. It can also allow arbitrary random access (seeking forwards or backwards to any location), or only sequential access (for example in the case of a socket or pipe).

就是说依据Stream所属类型,stream也将有各种能力,它可以read-only,write-only,read-write.除了读写基本操作能力,我们还需要能够指哪打哪的能力,那就任意访问Stream任何地方,即可以支持前后寻找seek。有些Stream可能only支持顺序访问(如socket和pipe stream),从头到尾依次访问。

前面已经提到过,Stream 分为:text I/O ,binary I/O ,raw I/O(即无buffer I/O)

这里不以文件对象类型来分类方法了,具体实现参考官档 :

  • close() flush 并 关闭Stream,相当于Stream 和 真实i/o设备 断开。但是文件对象还存在。不能再进行i/o操作了。
  • fileno() 返回Stream使用的底层文件描述符。如果没有报出异常。
  • flush() Flush buffers 中的数据到i/o设备中。对只读或这non-blocking Stream是不起作用的。
  • isatty() 如果Stream的i/o设备是一个交互终端,返回True。
  • readable() 如果Stream是可读的,那么返回True
  • readline(size=-1) 读取一行并返回该行,size指定了的话,返回对应的字节数。需要注意的是,对于二进制已b’\n’为行界定(包括b’\n’),对于文本, 已open()的newline参数为界定。
  • readlines(hint=-1) 将全部行读入一个list中并返回该list.hint指定的话,读取对应行数。最好少用,因为Stream是可迭代的,全取出来的话对内存消耗肯能很大。
  • seek(offset[,whence]) 改变Stream位置到字节offset。可以指定起点whence({‘start’:0,’cur’:1,’end’:2} or {‘start’:’SEEK_SET’,’cur’:’SEEK_CUR’,’end’:’SEEK_END’})。文本Stream一般只能已Stream开头偏移操作。字节Stream三种都支持。函数返回的都是seek后的绝对位置。
  • seekable() 判断Stream是否支持random access。即seek(),tell(),truncate()。
  • tell() 返回当前Stream 位置
  • truncate(size=None) Resize the Stream 到指定的size 字节(),如果本来Stream没有size大,那么使用zero-filled零添填充(utf-8对应的就是一个space空格的编码 )。没指定,就resize到当前位置,同样,当前位置如果超过了字节长度,那么也用zero-filled填充。大多系统是zero-filled,不排除其它填充。同时,truncate()操作不影响Stream的位置,说明了seek的访问范围不是Stream的长度,可以超出其长度,即就算Stream只有两个字节,seek也可以到3个字节处,也可以到100个字节处。 返回值是resize后的字节数。
  • writable() 判定Stream是否可写,即,write()和truncate()两个写操作。
  • writelines(lines) 写一个 list of lines to the Stream。Line separators are not added,so it is usaul for each of the lines provided to have a line separator at the end.就是,函数不会给每个元素后添加newline符。
  • read(size = -1) 读取指定size字节并return读取的字节。还分交互io还是非交互io.

Stream对象都是一个context manager,也是一个可迭代对象。

文件对象都是上下文管理器,能够用于with语法中。

with open('file','r') as fp:
     pass

with语句执行完毕后,自动关闭文件对象。
文件对象可迭代,用于for语句

with open('file','r') as fp:
    for line in fp:
        print(line)

TextStream和BufferedStream ,前者如果open指定了已指定newline符。后者已b’\n’字符定界行

理论后,实践操作

读取文件

#先创建文件
with open('test.txt','x') as fp:
    fp.write('Hello,world!\n')
    fp.write('Second Line!')
#进行read,readline,readlines和seek操作
fp1 = open(r'test.txt','r')
print(fp1.read())
fp1.seek(0)
print(fp1.readline())    
print(fp1.readline())
print(fp1.readline())
fp1.seek(0)
for line in fp1:
    print(line)
fp1.seek(0)
print(fp1.readlines())
fp1.close()

#已二进制读

with open(r'test.txt','rb') as fp2:
    for line in fp2:
        print(line)
    fp2.seek(0)
    print(fp2.read())
    fp2.seek(0)
    print(fp2.readline())
    print(fp2.readlines())
read接受的参数是字节,readline也是,readlines是行数。

写文件,有三种模式’w’,’x’,’a’

with open(r'test.txt','w+') as fp3:
    fp3.write("Hello,China!")
    fp3.seek(6)
    fp3.write("Franch")
    fp3.seek(0)
    print(fp3.read())  # 'Hello,Franch'
    fp3.flush()
with open('test.txt','a') as fp4:
    print(fp4.tell())  # 12
    fp4.write("\nHello,China!")
    fp4.seek(0)
    fp4.write("\nHello,Japan!")
    print(fp4.tell())  # 36

修改操作,修改要么全部数据读入内存,在回写覆盖。要么一单位一单位读,一单位一单位修改,一单位一单位写入另一个新文件,最后rename。
需求:文件test.txt 的Hello全部替换为 Nice to meet you

with open('test.txt','r') as fp1, open('test.txt.new','w') as fp2:
  cnt = 0
  for line in fp1:
    if 'Hello' in line:
      newline = line.replace('Hello','Nice to meet you')
      cnt += 1
    else:
      newline = line
    fp2.write(newline)
print(cnt)

python I/O 模块的结构是:IOBase 是顶层抽象

RawI/O就是低级的访问底层的OS设备或API,不会尝试将数据装入高级的单元中()
BufferedIOBase 字节Stream的基础类,支持各种类型buffering.
。。。只有参考官方文档->Generic Operating System Services->io

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这