python---文件处理

 

阅读目录

  • 一.文件处理流程
  • 二.基本操作
  • 2.1 文件操作基本流程初探
  • 2.2 文件编码
  • 2.3 文件打开模式
  • 2.4 文件内置函数flush
  • 2.5 文件内光标移动
  • 2.6 open函数详解

回到顶部

一.文件处理流程

  1. 打开文件,得到文件句柄并赋值给一个变量
  2. 通过句柄对文件进行操作
  3. 关闭文件
while True:
    print("选择需要的操作:")
    print("1 查询")
    print("2 删除")
    print("3 添加")
    print("4 修改")
    num=input("您的选择是:").strip()
    if num == '1':
        ##查询
        dic={"backend":""}
        dic["backend"]=input("请输入需要处理的域名:").strip()
        f_1=open("haproxy.conf",mode="r",encoding="utf8")
        flag=False
        li = []
        for line1 in f_1:
            if line1.startswith("backend") and  dic["backend"] in line1:
                flag=True
                continue
            if flag and "backend" in line1:
                flag = False
            if flag:
                li.append(line1.strip())
        f_1.close()
        print("select record:")
        for i in li:
            print(i)
    elif num =='2':
        ##删除
        dic={"backend":"","server":"","weight":"","maxconn":""}
        dic["backend"]=input("请输入需要删除的域名:").strip()
        dic["server"]=input("请输入此域名的ip:").strip()
        dic["weight"]=input("请输入此域名的weight:").strip()
        dic["maxconn"]=input("请输入此域名的maxconn:").strip()
        f_1=open("haproxy.conf",mode="r",encoding="utf8")
        f_2=open("haproxy2.conf",mode="w",encoding="utf8")

        flag=False
        li = []
        for line1 in f_1:
            if line1.startswith("backend") and  dic["backend"] in line1:
                f_2.write(line1)
                flag=True
                continue
            if flag and "backend" in line1:
                for i in li:
                    if dic["server"] in i and dic["weight"] in i and dic['maxconn'] in i:
                        continue
                    f_2.write(i)
                flag = False
            if flag:
                li.append(line1)
            if flag == False:
                f_2.write(line1)
        f_1.close()
        f_2.close()
        import os
        os.rename("haproxy.conf","haproxy.conf_bak")
        os.rename("haproxy2.conf","haproxy.conf")
    elif num == '4' :
        ##修改
        dic={"backend":"","server":"","weight":"","maxconn":""}
        dic["backend"]=input("请输入需要修改的域名:").strip()
        dic["server"]=input("请输入需要此域名的ip:").strip()
        dic["weight"]=input("请输入需要此域名weight修改为:").strip()
        dic["maxconn"]=input("请输入需要此域名maxconn修改为:").strip()

        f_1=open("haproxy.conf",mode="r",encoding="utf8")
        f_2=open("haproxy2.conf",mode="w",encoding="utf8")

        flag=False
        li = []
        for line1 in f_1:
            if line1.startswith("backend") and  dic["backend"] in line1:
                f_2.write(line1)
                flag=True
                continue
            if flag and "backend" in line1:
                for i in li:
                    if dic["server"] in i:
                        i="        server "+dic["server"]+" weight "+dic["weight"]+" maxconn "+dic['maxconn']+"\n"
                    f_2.write(i)
                flag = False
            if flag:
                li.append(line1)
            if flag == False:
                f_2.write(line1)

        f_1.close()
        f_2.close()
        import os
        os.rename("haproxy.conf","haproxy.conf_bak")
        os.rename("haproxy2.conf","haproxy.conf")
    elif num =='3':
        #添加
        dic={"backend":"","server":"","weight":"","maxconn":""}
        dic["backend"]=input("请输入需要添加到的域名:").strip()
        dic["server"]=input("请输入需要添加的ip:").strip()
        dic["weight"]=input("请输入需要添加的weight:").strip()
        dic["maxconn"]=input("请输入需要添加的maxconn:").strip()

        f_1=open("haproxy.conf",mode="r",encoding="utf8")
        f_2=open("haproxy2.conf",mode="w",encoding="utf8")

        flag=False
        li = []
        for line1 in f_1:
            if line1.startswith("backend") and  dic["backend"] in line1:
                f_2.write(line1)
                flag=True
                continue
            if flag and "backend" in line1:
                li.append("        server "+dic["server"]+" weight "+dic["weight"]+" maxconn "+dic['maxconn']+"\n")
                for i in li:
                    f_2.write(i)
                flag = False
            if flag:
                li.append(line1)
            if flag == False:
                f_2.write(line1)

        f_1.close()
        f_2.close()
        import os
        os.rename("haproxy.conf","haproxy.conf_bak")
        os.rename("haproxy2.conf","haproxy.conf")
    elif num == 'q':
        break
    else :
        print("输入错误,请重新输入")
示列

 

二.基本操作

回到顶部

2.1 文件操作基本流程初探

f = open('chenli.txt') #打开文件
first_line = f.readline()
print('first line:',first_line) #读一行
print('我是分隔线'.center(50,'-'))
data = f.read()# 读取剩下的所有内容,文件大时不要用
print(data) #打印读取内容
 
f.close() #关闭文件
View Code

2.2 文件编码

文件保存编码如下

 

此刻错误的打开方式
#不指定打开编码,即python解释器默认编码,python2.*为ascii,python3.*为utf-8
f=open('chenli.txt')
f.read() 

 

正确的打开方式
f=open('chenli.txt',mod='r'encoding='gbk')
f.read()

回到顶部

2.3 文件打开模式

1 文件句柄 = open('文件路径', '模式')

 

打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作。

打开文件的模式有:

  • r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】
  • w,只写模式【不可读;不存在则创建;存在则清空内容】
  • x, 只写模式【不可读;不存在则创建,存在则报错】
  • a, 追加模式【可读;   不存在则创建;存在则只追加内容】

"+" 表示可以同时读写某个文件

  • r+, 读写【可读,可写】
  • w+,写读【可读,可写】
  • x+ ,写读【可读,可写】
  • a+, 写读【可读,可写】

 "b"表示以字节的方式操作

  • rb  或 r+b
  • wb 或 w+b
  • xb 或 w+b
  • ab 或 a+b

 注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

回到顶部

2.4 文件内置函数flush

flush原理:

  1. 文件操作是通过软件将文件从硬盘读到内存
  2. 写入文件的操作也都是存入内存缓冲区buffer(内存速度快于硬盘,如果写入文件的数据都从内存刷到硬盘,内存与硬盘的速度延迟会被无限放大,效率变低,所以要刷到硬盘的数据我们统一往内存的一小块空间即buffer中放,一段时间后操作系统会将buffer中数据一次性刷到硬盘)
  3. flush即,强制将写入的数据刷到硬盘

import sys,time
 
for i in  range(10):
    sys.stdout.write('#')
    sys.stdout.flush()
    time.sleep(0.2)
滚动条:
import sys                                  
for i in range(100):
      i += 1
    s="\r%d%% %s"%(i,"#"*i)
    sys.stdout.write(s)                            
    sys.stdout.flush()
    import time
    time.sleep(0.5)
进度条示列

 

 

回到顶部

2.5 文件内光标移动

注意:read(3)代表读取3个字符,其余的文件内光标移动都是以字节为单位如seek,tell,read,truncate

整理中

回到顶部

2.6 open函数详解

1. open()语法

open(file[, mode[, buffering[, encoding[, errors[, newline[, closefd=True]]]]]])
open函数有很多的参数,常用的是file,mode和encoding
file文件位置,需要加引号
mode文件打开模式,见下面3
buffering的可取值有0,1,>1三个,0代表buffer关闭(只适用于二进制模式),1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小;
encoding表示的是返回的数据采用何种编码,一般采用utf8或者gbk;
errors的取值一般有strict,ignore,当取strict的时候,字符编码出现问题的时候,会报错,当取ignore的时候,编码出现问题,程序会忽略而过,继续执行下面的程序。
newline可以取的值有None, \n, \r, ”, ‘\r\n',用于区分换行符,但是这个参数只对文本模式有效;
closefd的取值,是与传入的文件参数有关,默认情况下为True,传入的file参数为文件的文件名,取值为False的时候,file只能是文件描述符,什么是文件描述符,就是一个非负整数,在Unix内核的系统中,打开一个文件,便会返回一个文件描述符。

2. Python中file()与open()区别
两者都能够打开文件,对文件进行操作,也具有相似的用法和参数,但是,这两种文件打开方式有本质的区别,file为文件类,用file()来打开文件,相当于这是在构造文件类,而用open()打开文件,是用python的内建函数来操作,建议使用open
View Code

 

3. 参数mode的基本取值

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

‘b'

binary mode

‘t'

text mode (default)

‘+'

open a disk file for updating (reading and writing)

‘U'

universal newline mode (for backwards compatibility; should not be used in new code)

r、w、a为打开文件的基本模式,对应着只读、只写、追加模式;
b、t、+、U这四个字符,与以上的文件打开模式组合使用,二进制模式,文本模式,读写模式、通用换行符,根据实际情况组合使用、

常见的mode取值组合

View Code

 

文件操作

9.1 对文件操作流程

打开文件,得到文件句柄并赋值给一个变量
通过句柄对文件进行操作
关闭文件
     现有文件如下:     
昨夜寒蛩不住鸣。
惊回千里梦,已三更。
起来独自绕阶行。
人悄悄,帘外月胧明。
白首为功名,旧山松竹老,阻归程。
欲将心事付瑶琴。
知音少,弦断有谁听。

f = open('小重山') #打开文件
data=f.read()#获取文件内容
f.close() #关闭文件
注意 if in the win,hello文件是utf8保存的,打开文件时open函数是通过操作系统打开的文件,而win操作系统

默认的是gbk编码,所以直接打开会乱码,需要f=open('hello',encoding='utf8'),hello文件如果是gbk保存的,则直接打开即可。

9.2 文件打开模式  
========= ===============================================================
    Character Meaning
    --------- ---------------------------------------------------------------
    'r'       open for reading (default)
    'w'       open for writing, truncating the file first
    'x'       create a new file and open it for writing
    'a'       open for writing, appending to the end of the file if it exists
    'b'       binary mode
    't'       text mode (default)
    '+'       open a disk file for updating (reading and writing)
    'U'       universal newline mode (deprecated)
    ========= ===============================================================
先介绍三种最基本的模式:

# f = open('小重山2','w') #打开文件
# f = open('小重山2','a') #打开文件
# f.write('莫等闲1\n')
# f.write('白了少年头2\n')
# f.write('空悲切!3')
9.3 文件具体操作


复制代码
def read(self, size=-1): # known case of _io.FileIO.read
        """
        注意,不一定能全读回来
        Read at most size bytes, returned as bytes.

        Only makes one system call, so less data may be returned than requested.
        In non-blocking mode, returns None if no data is available.
        Return an empty bytes object at EOF.
        """
        return ""

def readline(self, *args, **kwargs):
        pass

def readlines(self, *args, **kwargs):
        pass


def tell(self, *args, **kwargs): # real signature unknown
        """
        Current file position.

        Can raise OSError for non seekable files.
        """
        pass

def seek(self, *args, **kwargs): # real signature unknown
        """
        Move to new file position and return the file position.

        Argument offset is a byte count.  Optional argument whence defaults to
        SEEK_SET or 0 (offset from start of file, offset should be >= 0); other values
        are SEEK_CUR or 1 (move relative to current position, positive or negative),
        and SEEK_END or 2 (move relative to end of file, usually negative, although
        many platforms allow seeking beyond the end of a file).

        Note that not all file objects are seekable.
        """
        pass

def write(self, *args, **kwargs): # real signature unknown
        """
        Write bytes b to file, return number written.

        Only makes one system call, so not all of the data may be written.
        The number of bytes actually written is returned.  In non-blocking mode,
        returns None if the write would block.
        """
        pass

def flush(self, *args, **kwargs):
        pass


def truncate(self, *args, **kwargs): # real signature unknown
        """
        Truncate the file to at most size bytes and return the truncated size.

        Size defaults to the current file position, as returned by tell().
        The current file position is changed to the value of size.
        """
        pass


def close(self): # real signature unknown; restored from __doc__
            """
            Close the file.

            A closed file cannot be used for further I/O operations.  close() may be
            called more than once without error.
            """
            pass
##############################################################less usefull
    def fileno(self, *args, **kwargs): # real signature unknown
            """ Return the underlying file descriptor (an integer). """
            pass

    def isatty(self, *args, **kwargs): # real signature unknown
        """ True if the file is connected to a TTY device. """
        pass

    def readable(self, *args, **kwargs): # real signature unknown
        """ True if file was opened in a read mode. """
        pass

    def readall(self, *args, **kwargs): # real signature unknown
        """
        Read all data from the file, returned as bytes.

        In non-blocking mode, returns as much as is immediately available,
        or None if no data is available.  Return an empty bytes object at EOF.
        """
        pass

    def seekable(self, *args, **kwargs): # real signature unknown
        """ True if file supports random-access. """
        pass


    def writable(self, *args, **kwargs): # real signature unknown
        """ True if file was opened in a write mode. """
        pass
复制代码
f = open('小重山') #打开文件
# data1=f.read()#获取文件内容
# data2=f.read()#获取文件内容
#
# print(data1)
# print('...',data2)
# data=f.read(5)#获取文件内容
 
# data=f.readline()
# data=f.readline()
# print(f.__iter__().__next__())
# for i in range(5):
#     print(f.readline())
 
# data=f.readlines()
 
# for line in f.readlines():
#     print(line)
 
 
# 问题来了:打印所有行,另外第3行后面加上:'end 3'
# for index,line in enumerate(f.readlines()):
#     if index==2:
#         line=''.join([line.strip(),'end 3'])
#     print(line.strip())
 
#切记:以后我们一定都用下面这种
# count=0
# for line in f:
#     if count==3:
#         line=''.join([line.strip(),'end 3'])
#     print(line.strip())
#     count+=1
 
# print(f.tell())
# print(f.readline())
# print(f.tell())#tell对于英文字符就是占一个,中文字符占三个,区分与read()的不同.
# print(f.read(5))#一个中文占三个字符
# print(f.tell())
# f.seek(0)
# print(f.read(6))#read后不管是中文字符还是英文字符,都统一算一个单位,read(6),此刻就读了6个中文字符
 
#terminal上操作:
f = open('小重山2','w')
# f.write('hello \n')
# f.flush()
# f.write('world')
 
# 应用:进度条
# import time,sys
# for i in range(30):
#     sys.stdout.write("*")
#     # sys.stdout.flush()
#     time.sleep(0.1)
 
 
# f = open('小重山2','w')
# f.truncate()#全部截断
# f.truncate(5)#全部截断
 
 
# print(f.isatty())
# print(f.seekable())
# print(f.readable())
 
f.close() #关闭文件
接下来我们继续扩展文件模式:
# f = open('小重山2','w') #打开文件
# f = open('小重山2','a') #打开文件
# f.write('莫等闲1\n')
# f.write('白了少年头2\n')
# f.write('空悲切!3')
 
 
# f.close()
 
#r+,w+模式
# f = open('小重山2','r+') #以读写模式打开文件
# print(f.read(5))#可读
# f.write('hello')
# print('------')
# print(f.read())
 
 
# f = open('小重山2','w+') #以写读模式打开文件
# print(f.read(5))#什么都没有,因为先格式化了文本
# f.write('hello alex')
# print(f.read())#还是read不到
# f.seek(0)
# print(f.read())
 
#w+与a+的区别在于是否在开始覆盖整个文件
 
 
# ok,重点来了,我要给文本第三行后面加一行内容:'hello 岳飞!'
# 有同学说,前面不是做过修改了吗? 大哥,刚才是修改内容后print,现在是对文件进行修改!!!
# f = open('小重山2','r+') #以写读模式打开文件
# f.readline()
# f.readline()
# f.readline()
# print(f.tell())
# f.write('hello 岳飞')
# f.close()
# 和想的不一样,不管事!那涉及到文件修改怎么办呢?
 
# f_read = open('小重山','r') #以写读模式打开文件
# f_write = open('小重山_back','w') #以写读模式打开文件
 
# count=0
# for line in f_read:
    # if count==3:
    #     f_write.write('hello,岳飞\n')
    #
    # else:
    #     f_write.write(line)
 
 
    # another way:
    # if count==3:
    #
    #     line='hello,岳飞2\n'
    # f_write.write(line)
    # count+=1
 
 
# #二进制模式
# f = open('小重山2','wb') #以二进制的形式读文件
# # f = open('小重山2','wb') #以二进制的形式写文件
# f.write('hello alvin!'.encode())#b'hello alvin!'就是一个二进制格式的数据,只是为了观看,没有显示成010101的形式
注意1:  无论是py2还是py3,在r+模式下都可以等量字节替换,但没有任何意义的! 

注意2:有同学在这里会用readlines得到内容列表,再通过索引对相应内容进行修改,最后将列表重新写会该文件。

           这种思路有一个很大的问题,数据若很大,你的内存会受不了的,而我们的方式则可以通过迭代器来优化这个过程。 

补充:rb模式以及seek

在py2中:

#昨夜寒蛩不住鸣.
 
f = open('test','r',) #以写读模式打开文件
 
f.read(3)
 
# f.seek(3)
# print f.read(3) # 夜
 
# f.seek(3,1)
# print f.read(3) # 寒
 
# f.seek(-4,2)
# print f.read(3) # 鸣
在py3中:

复制代码
# test: 
昨夜寒蛩不住鸣.

f = open('test','rb',) #以写读模式打开文件

f.read(3)

# f.seek(3)
# print(f.read(3)) # b'\xe5\xa4\x9c'

# f.seek(3,1)
# print(f.read(3)) # b'\xe5\xaf\x92'

# f.seek(-4,2)
# print(f.read(3))   # b'\xe9\xb8\xa3'

#总结: 在py3中,如果你想要字符数据,即用于观看的,则用r模式,这样我f.read到的数据是一个经过decode的
#     unicode数据; 但是如果这个数据我并不需要看,而只是用于传输,比如文件上传,那么我并不需要decode
#     直接传送bytes就好了,所以这个时候用rb模式.

#     在py3中,有一条严格的线区分着bytes和unicode,比如seek的用法,在py2和py3里都是一个个字节的seek,
#     但在py3里你就必须声明好了f的类型是rb,不允许再模糊.

#建议: 以后再读写文件的时候直接用rb模式,需要decode的时候仔显示地去解码.
复制代码
9.4 with语句

为了避免打开文件后忘记关闭,可以通过管理上下文,即:


with open('log','r') as f:
        pass
如此方式,当with代码块执行完毕时,内部会自动关闭并释放文件资源。

在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:


with open('log1') as obj1, open('log2') as obj2:
    pass
  
*****小世界*****

 知识扩展:

Python file操作

打开文固定格式
变量名 = open(文件路径,模式,编码)
需要最后进行文件关闭操作
with open(文件路径,模式,编码) as 变量名:
with可以打开多个,用,分开即可。
打开文件模式说明
模式	描述
r	以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb	以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
r+	打开一个文件用于读写。文件指针将会放在文件的开头。
rb+	以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
w	打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb	以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
w+	打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
wb+	以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a	打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab	以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+	打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+	以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
文件操作命令
f.read() 读取文件全部内容
f.write(str) 写入文件
f.readable() 读取文件
f.readline() 读取一行文件内容
f.readlines()读取文件全部内容,存放格式为列表

f.close()关闭文件
f.closed() 查看文件是否关闭
f.name() 查看文件名称

f.seek() 查看光标位置


for i in f:读文件最好是用for读取每行
文件写入

write(str) 

写入传入参数必须是一个字符串格式
打开文件注意事项

    文件打开使用完毕后必须关闭,with 不需要

    文件打开的编码,以什么格式存,就以什么格式打开。

文件重命名及删除

import os

需要导入os模块

os.rename(old,new) 将旧文件名重命名为新文件名

os.remove(filename) 删除文件

 

posted @ 2017-04-24 15:03  『心向阳﹡无所惧』  阅读(322)  评论(0)    收藏  举报