1、文件操做

      打开文件时,须要指定文件路径和以何等方式打开文件,打开后,便可获取该文件句柄,往后经过此文件句柄对该文件操做。html

打开文件的模式有:java

  • r ,只读模式【默认模式,文件必须存在,不存在则抛出异常】(不加mode时默认为r模式)
  • w,只写模式【不可读;不存在则建立;存在则清空内容】(至关于从新建立了文件)
  • x, 只写模式【不可读;不存在则建立,存在则报错】
  • a, 追加模式【不可读;   不存在则建立;存在则只追加内容】

"+" 表示能够同时读写某个文件python

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

"U"表示在读取时,能够将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)sql

  • rU
  • r+U

 "b"表示以字节的方式操做数据库

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

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

文件操做各类方法详解

方法 描述
f.close() 关闭文件,记住用open()打开文件后必定要记得关闭它,不然会占用系统的可打开文件句柄数。
f.fileno() 得到文件描述符,是一个数字
f.flush() 刷新输出缓存
f.isatty() 若是文件是一个交互终端,则返回True,不然返回False。
f.read([count]) 默认读出所有文件,若是有count,则读出count个字符。
f.readline() 读出一行信息。
f.readlines() 读出全部行,也就是读出整个文件的信息。
f.seek(offset[,where]) 把文件指针移动到相对于where的offset位置。where为0表示文件开始处,这是默认值 ;1表示当前位置;2表示文件结尾。
f.seekable() 判断光标是否可移动,像tty文件或终端设备文件光标不可移动
f.tell() 得到文件指针位置。
f.truncate([size]) 截取文件,使文件的大小为size。
f.write(string) 把string字符串写入文件。
f.writelines(list) 把list中的字符串一行一行地写入文件,是连续写入文件,没有换行。

示例文件windows

Somehow, it seems the love I knew was always the most destructive kind
不知为什么,我经历的爱情老是最具毁灭性的的那种
Yesterday when I was young
昨日当我年少轻狂
The taste of life was sweet
生命的滋味是甜的
As rain upon my tongue
就如舌尖上的雨露
I teased at life as if it were a foolish game
我戏弄生命 视其为愚蠢的游戏
The way the evening breeze
就如夜晚的微风
May tease the candle flame
逗弄蜡烛的火苗
The thousand dreams I dreamed
我曾千万次梦见
The splendid things I planned
那些我计划的绚丽蓝图
I always built to last on weak and shifting sand
但我老是将之建筑在易逝的流沙上
I lived by night and shunned the naked light of day
我夜夜笙歌 逃避白昼赤裸的阳光
And only now I see how the time ran away
事到现在我才看清岁月是如何匆匆流逝
Yesterday when I was young
昨日当我年少轻狂
So many lovely songs were waiting to be sung
有那么多甜美的曲儿等我歌唱
So many wild pleasures lay in store for me
有那么多肆意的快乐等我享受
And so much pain my eyes refused to see
还有那么多痛苦 个人双眼却视而不见
I ran so fast that time and youth at last ran out
我飞快地奔走 最终时光与青春消逝殆尽
I never stopped to think what life was all about
我从未停下脚步去思考生命的意义
And every conversation that I can now recall
现在回想起的全部对话
Concerned itself with me and nothing else at all
除了和我相关的 什么都记不得了
The game of love I played with arrogance and pride
我用自负和傲慢玩着爱情的游戏
And every flame I lit too quickly, quickly died
全部我点燃的火焰都熄灭得太快
The friends I made all somehow seemed to slip away
全部我交的朋友彷佛都不知不觉地离开了
And only now I'm left alone to end the play, yeah
只剩我一我的在台上来结束这场闹剧
Oh, yesterday when I was young
噢 昨日当我年少轻狂
So many, many songs were waiting to be sung
有那么那么多甜美的曲儿等我歌唱
So many wild pleasures lay in store for me
有那么多肆意的快乐等我享受
And so much pain my eyes refused to see
还有那么多痛苦 个人双眼却视而不见
There are so many songs in me that won't be sung
我有太多歌曲永远不会被唱起
I feel the bitter taste of tears upon my tongue
我尝到了舌尖泪水的苦涩滋味
The time has come for me to pay for yesterday
终于到了付出代价的时间 为了昨日
When I was young
当我年少轻狂
View Code

read():读取文件所有python3.x

打开文件并所有读出(read()方法)缓存

f = open("demo", 'r', encoding="utf-8")
print(f.read())

write():写入文件(写入时指定编码,wb形式没法指定)app

f = open("demo", 'w', encoding="utf-8")
f.write('看看效果了\n')
f.write('换行了,不加反斜杠n不换行')

readline():读取文件一行

f = open("demo", 'w', encoding="utf-8")
print(f.readline().strip())
print(f.readline().strip())
print(f.readline().strip())
print(f.readline().strip())

readlines():将文件全部按行划分红列表元素并装入列表

f = open('demo', 'r', encoding='utf-8')
print(f.readlines())

# ['Somehow, it seems the love I knew was always the most destructive kind\n', '不知为什么,我经历的爱情老是最具毁灭性的的那种\n',............'终于到了付出代价的时间 为了昨日\n', 'When I was young\n', '当我年少轻狂']

for line in f.readlines():  # 循环打印全部
    print(line.strip())

# 跳过第九行打印
for index, line in enumerate(f.readlines()):
    if index == 9:
        print("==========================")
        continue
    print(line.strip())

注:循环读出文件建议以下

for line in f:  # 这样机器内存里值保存一行,最高效

  print(line)

tell():返回文件内光标所在位置

f = open('demo', 'r', encoding='utf-8')
f.readline()
f.readline()
print(f.tell())

# 140

seek():将文件内光标移到指定位置

read()和write()都是在光标后读写,r+模式的默认例外

f.readline()
f.readline()
f.seek(2)
print(f.tell())

# 2

flush():将文件实时刷新到硬盘上(python3.x)

文件运行时是与缓存交换信息,等缓存满了,缓存一次性刷到硬盘,硬盘(存二进制,插入需后面全日后移,不现实)改东西 只能覆盖,不能插入
truncate():将文件截断指定大小,默认截断0
f.encoding   #查看使用open打开文件的编码
f.closed       #文件若是关闭则返回True

文件打开模式分析

‘r’模式:只读模式

只能读取文件,是默认模式,文件必须存在,不存在则抛出异常

read()和write()都是在光标后读写,r+模式的默认例外

‘w’模式:只写模式

用了只写模式至关于从新建立问价,不可读;不存在则建立;存在则清空内容重写

’a’模式:追加模式

可读;不存在则建立;存在则只追加内容。不管光标在哪,是否使用seek,追加模式只能在文件的末尾进行写(追加)操做(a,a+)

’r+’模式:读写模式

可读可写,在不手动用seek()移动光标时,write()默认会写到文件的最后,其他模式都是在光标后操做,由于在文件内写是覆盖,并非插入,为了保护文件

可是若本身手动seek()移动了光标,则可在seek()处写(实际上是覆盖)(对比a,a+)

可是覆盖也有问题(可能会有编码错误)

‘w+’模式:写读模式

可读可写,可是由于是写读模式,相似‘w’模式,至关于从新建立文件,因此只能先写在读

‘rb’模式:二进制读模式

二进制的方式读取,不须要加编码方式

f = open ( 'dingxi' , 'rb' )

文件修改

f=open('dingxi','r',encoding='utf8')
new_f=open('dingxi2','w',encoding='utf8')
for line in f:
    if '多想和你同样臭不要脸' in line:
        line = line.replace('多想和你同样臭不要脸','就是这么的臭不要脸')
    new_f.write(line)
f.close()
new_f.close()

# 执行结果:建立一个新的文件,而且替换原来的‘多想和你同样臭不要脸’

with语句

为了不打开文件后忘记关闭,能够经过with管理上下文,当with代码块执行完毕时,内部会自动关闭并释放文件资源。with语句的基本语法结构以下:

with expression [as variable]:
    with-block

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

with open('dingxi','r',encoding='utf8') as f,open('Lry','r',encoding='utf8') as f1:
    print(f.readline())
    print(f1.readline())

  是否是发现使用with语句相对try/finally来讲简洁了不少,并且也不须要每个用户都去写f.close()来关闭文件了,这是由于with语句在背后作了大量的工做。with语句的expression是上下文管理器,这个咱们下文会说。with语句中的[as variable]是可选的,若是指定了as variable说明符,则variable是上下文管理器expression调用__enter__()函数返回的对象。因此,f并不必定就是expression,而是expression.__enter__()的返回值,至于expression.__enter__()返回什么就由这个函数来决定了。with-block是执行语句,with-block执行完毕时,with语句会自动进行资源清理,对应上面例子就是with语句会自动关闭文件。

  下面咱们来具体说下with语句在背后默默无闻地到底作了哪些事情。刚才咱们说了expression是一个上下文管理器,其实现了__enter__和__exit__两个函数。当咱们调用一个with语句时,执行过程以下:

1.首先生成一个上下文管理器expression,在上面例子中with语句首先以“test.txt”做为参数生成一个上下文管理器open("test.txt")。

2.而后执行expression.__enter__()。若是指定了[as variable]说明符,将__enter__()的返回值赋给variable。上例中open("test.txt").__enter__()返回的是一个文件对象给f。

3.执行with-block语句块。上例中执行读取文件。

4.执行expression.__exit__(),在__exit__()函数中能够进行资源清理工做。上面例子中就是执行文件的关闭操做。

  with语句不只能够管理文件,还能够管理锁、链接等等,以下面的例子:

#管理锁
import  threading
lock = threading.lock()
with lock:
    #执行一些操做
    pass

下文管理器


   在上文中咱们提到with语句中的上下文管理器。with语句能够如此简单但强大,主要依赖于上下文管理器。那么什么是上下文管理器?上下文管理器就是实现了上下文协议的类,而上下文协议就是一个类要实现__enter__()和__exit__()两个方法。一个类只要实现了__enter__()和__exit__(),咱们就称之为上下文管理器下面咱们具体说下这两个方法。

  __enter__():主要执行一些环境准备工做,同时返回一资源对象。若是上下文管理器open("test.txt")的__enter__()函数返回一个文件对象。

  __exit__():完整形式为__exit__(type, value, traceback),这三个参数和调用sys.exec_info()函数返回值是同样的,分别为异常类型、异常信息和堆栈。若是执行体语句没有引起异常,则这三个参数均被设为None。不然,它们将包含上下文的异常信息。__exit_()方法返回True或False,分别指示被引起的异常有没有被处理,若是返回False,引起的异常将会被传递出上下文。若是__exit__()函数内部引起了异常,则会覆盖掉执行体的中引起的异常。处理异常时,不须要从新抛出异常,只须要返回False,with语句会检测__exit__()返回False来处理异常。

  若是咱们要自定义一个上下文管理器,只须要定义一个类而且是实现__enter__()和__exit__()便可。下面经过一个简单的例子是演示若是新建自定义的上下文管理器,咱们以数据库的链接为例。在使用数据库时,有时要涉及到事务操做。数据库的事务操做当调用commit()执行sql命令时,若是在这个过程当中执行失败,则须要执行rollback()回滚数据库,一般实现方式可能以下:

def test_write():
    con = MySQLdb.connection()
    cursor = con.cursor()
    sql = """      #具体的sql语句
    """
    try:
        cursor.execute(sql)
        cursor.execute(sql)
        cursor.execute(sql)
        con.commit()      #提交事务
    except Exception as ex:
        con.rollback()    #事务执行失败,回滚数据库

  若是想经过with语句来实现数据库执行失败的回滚操做,则咱们须要自定义一个数据库链接的上下文管理器,假设为DBConnection,则咱们将上面例子用with语句来实现的话,应该是这样子的,以下:

def test_write():
    sql = """      #具体的sql语句
    """
    con = DBConnection()
    with con as cursor:   
        cursor.execute(sql)
        cursor.execute(sql)
        cursor.execute(sql)

  要实现上面with语句的功能,则咱们的DBConnection数据库上下文管理器则须要提供一下功能:__enter__()要返回一个链接的cursor; 当没有异常发生是,__exit__()函数commit全部的数据库操做。若是有异常发生则_exit__()会回滚数据库,调用rollback()。因此咱们能够实现DBConnection以下:

def DBConnection(object):
    def __init__(self):
        pass

    def cursor(self):
        #返回一个游标而且启动一个事务
        pass

    def commit(self):
        #提交当前事务
        pass

    def rollback(self):
        #回滚当前事务
        pass

    def __enter__(self):
        #返回一个cursor
        cursor = self.cursor()
        return cursor

    def __exit__(self, type, value, tb):
        if tb is None:
            #没有异常则提交事务
            self.commit() 
        else:
            #有异常则回滚数据库
            self.rollback()

Python 文件夹及文件操做

咱们常常会与文件和目录打交道,对于这些操做,python可使用 os 及 shutill 模块,其中包含了不少操做文件和目录的函数。

  os 能够执行简单的文件夹及文件操做,引入用  import os,可用  help(os)  或是  dir(os)  查看其用法。注意有些函数在os模块中,有的是在os.path模块中。

  shutil 模块提供了大量的文件的高级操做,特别针对文件拷贝和删除。主要功能为目录和文件操做以及压缩操做。须引入 import shutil  ,具体 help。本文仅介绍移动、复制及删除。

  可先在 D:\ 下建立文件夹 Python_os , 再在其下建立文件夹 os, 再在其下建立 test.txt;以后的示例会在该文件夹下操做

      

判断路径或文件

    os.path.isabs(...)      # 判断是否绝对路径

    os.path.exists(...)     # 判断是否真实存在

    os.path.isdir(...)       # 判断是不是个目录

    os.path.isfile(...)       # 判断是不是个文件

  注意:   把两个路径合成一个时,不要直接拼字符串,而要经过 os.path.join(part1,part2) 函数,这样能够正确处理不一样操做系统的路径分隔符。在Linux/Unix/Mac下,os.path.join()返回这样的字符串:    part1/part2

  而Windows下会返回这样的字符串:  part1\part2

复制代码
 1 import os
 2 import shutil
 3 
 4 file_dir = "D:\\Python_os\\os"                          # 注意 \\ ;windows 下是这么表示的;Linux 和 Mac 是 /
 5 file_name = "test.txt"
 6 file_abs = os.path.join(file_dir, file_name)            # os.path.join(...) 表示路径连接
 7 
 8 
 9 '''判断路径或文件'''
10 print (1,os.path.isabs(file_dir))                       # 判断是否绝对路径
11 print (2,os.path.isabs(file_name))                        
12 print (3,os.path.isabs(file_abs))                        
13 print (4,os.path.exists(file_abs))                      # 判断是否真实存在
14 print (5,os.path.exists(os.path.join(file_dir,"xxx")))                
15 print (6,os.path.isdir(file_dir))                       # 判断是不是个目录
16 print (7,os.path.isdir(file_abs))        
17 print (8,os.path.isfile(file_dir))                      # 判断是不是个文件
18 print (9,os.path.isfile(file_abs))        
复制代码

运行结果: 

 

路径名、文件名分隔

    os.path.split(...)            # 分隔目录和文件名/文件夹名         

    os.path.splitdrive(...)        # 分隔盘符(windows系统)     

    os.path.splitext(...)           # 分隔文件和扩展名

运行结果:  

这些合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操做。

 

工做目录及建立文件夹操做

    os.getcwd()       # 获取当前工做目录

    os.chdir(...)       # 改变工做目录

    os.listdir(...)      # 列出目录下的文件

    os.mkdir(...)      # 建立单个目录        注意:建立多级用 os.makedirs()

    os.makedirs(...)    # 建立多级目录

复制代码
 1 import os
 2 
 3 file_dir = "D:\\Python_os\\os"    
 4 
 5 print (os.getcwd())                                # 获取当前工做目录
 6 os.chdir(file_dir)                                 # 改变工做目录
 7 print (os.getcwd())    
 8 print (os.listdir(file_dir))                       # 列出当前工做目录的全部文件 Python2 不支持 os.listdir()    Python3 会列出当前工做目录下的全部文件      
 9 os.mkdir("test_mkdir")                             # 在当前工做目录下建立文件夹 test_mkdir;注意不可存在相同文件夹,否则会报错
10 os.makedirs("test_mkdir\\test1")
11 os.chdir(".\\test_mkdir")                          # . 表示本级目录; .. 表示上级目录
12 print (os.getcwd())    
13 for i in range(2,6):                               # 使用for循环等,可方便的建立多个文件夹
14     dir_name = "test" + str(i)
15     os.mkdir(dir_name)    
复制代码

在执行了上述实例代码后,os 文件夹中新建了空的 test_mkdir 文件夹,而 test_dir 文件夹下也新建出了 test1 至 test5 的空文件夹

   

 建立文件夹可能会出错,缘由具体有:(1) path 已存在时(不论是文件仍是文件夹)  (2) 驱动器不存在  (3) 磁盘已满  (4) 磁盘是只读的或没有写权限

删除文件夹/文件

    os.rmdir(...)            # 删除空文件夹                     注意:必须为空文件夹  如需删除文件夹及其下全部文件,需用 shutil

    os.remove(...)                   # 删除单一文件

    shutil.rmtree(...)               # 删除文件夹及其下全部文件

在上方示例的文件夹基础上,操做删除 test1 文件夹 (空文件夹可用 os.rmdir() ),删除 test_mkdir 及其下全部文件();示例代码以下

复制代码
 1 import os
 2 import shutil
 3 
 4 file_dir = "D:\\Python_os\\os"                    
 5 
 6 ''' 删除文件/文件夹 '''
 7 os.chdir(file_dir+"\\test_mkdir")                    
 8 print(os.getcwd())                                    # 确保当前工做目录
 9 print(os.listdir(os.getcwd()))                        # 查看当前文件夹下全部文件    
10 os.rmdir("test1")                                     # 删除 test1 文件夹(空文件夹)
11 print(os.listdir(os.getcwd()))    
12 os.chdir("..\\")
13 print(os.getcwd())                                    # 切换到上级目录
14 print(os.listdir(os.getcwd()))
15 shutil.rmtree("test_mkdir")                           # 删除 test_mkdir 及其下全部文件
复制代码

 可见运行结果以下;产生异常的可能缘由:  (1) 路径不存在 (2) 路径子目录中有文件或下级子目录(os.rmdir) (3) 没有操做权限或只读

只是删除单一文件,则用   os.remove("test.txt")   便可;产生异常的可能缘由:  (1) 文件不存在   (2) 对该文件没有操做权限或只读。

 

重命名文件夹/文件

可对某一文件或文件夹重命名   os.rename(oldfileName, newFilename)  

在os文件夹中新建文件夹 test,文件 test.txt  

复制代码
1 ''' 重命名文件夹/文件 '''
2 os.chdir(file_dir)
3 print(os.listdir(os.getcwd()))
4 os.rename("test","test1")    
5 os.rename("test.txt","test1.txt")                # 重命名,注意须要带扩展名
6 print(os.listdir(os.getcwd()))
复制代码

可见运行结果以下;产生异常的可能缘由:  (1) oldfilename 旧文件名不存在(文件须带扩展名)   (2)newFilename 新文件已经存在

注意:新文件的扩展名不能遗漏,理论上须要保持类型一致;但这也不失为改文件类型的一种方式(至关于直接改文件的扩展名) 

复制、移动文件夹/文件

须使用 shutil 模块,引入 import shutil 

    shutil.copyfile("old","new")       # 复制文件,都只能是文件

    shutil.copytree("old","new")     # 复制文件夹,都只能是目录,且new必须不存在

    shutil.copy("old","new")           # 复制文件/文件夹,复制 old 为 new(new是文件,若不存在,即新建),复制 old 为至 new 文件夹(文件夹已存在)

    shutil.move("old","new")          # 移动文件/文件夹至 new 文件夹中

咱们如今 D:\ 下建立新文件夹 Python_shutil ,而后工做目录切到该目录,直接使用 Python 来操做吧,参考代码以下:

复制代码
1 import os
2 import shutil
3 
4 os.chdir("D:\\")
5 os.mkdir("Python_shutil")
6 file_dir = "D:\\Python_shutil"
7 os.chdir(file_dir)
复制代码

为演示复制、移动操做,咱们在该文件夹下手动操做 新建文件夹 test_org、 test_copy 及 test_move; 新建文件 test.txt  test1.txt , 二者内容不一样

   

Python 复制、移动的操做示例代码以下:

复制代码
 1 import os
 2 import shutil
 3 
 4 file_dir = "D:\\Python_shutil"
 5 os.chdir(file_dir)
 6 shutil.copyfile("test_org.txt","test_copy.txt")        # copy test_org.txt 为 test_copy.txt 若存在,则覆盖
 7 shutil.copyfile("test_org.txt","test1.txt")            # 存在,覆盖
 8 shutil.copytree("test_org","test_copytree")            # copy test_org 为 test_copytree(不存在的新目录)
 9 shutil.copy("test_org.txt","test_copy1.txt")           # 同 copyfile
10 shutil.copy("test_org.txt","test_copy")                # 将文件 copy 至 目标文件夹中(须存在)
11 shutil.copy("test_org.txt","test_xxx")                 # 将文件 copy 至 目标文件(该文件可不存在,注意类型!)
12 print os.listdir(os.getcwd())
13 shutil.move("test_org.txt","test_move")                # 将文件 move 至 目标文件夹中
14 shutil.move("test_org","test_move")                    # 将文件夹 move 至 目标文件夹中
15 print os.listdir(os.getcwd())
复制代码

 

   

文件操做实例

 复制粘贴博主的java教程中的doc文件

# Tools:Pycharm 2017.3.2
# author ="wlx"
__date__ = '2018/8/13 9:43'
import os
import shutil
path_root = 'G:\java教程\day'
path_append_list = os.listdir(path_root)  # 子目录集
path_joint_list = []  # 须要进入的子目录集
for p in path_append_list:  # 拼接后的目录集
    path_joint_list.append(path_root+"\\"+p)
file_joint_list = []  # 存须要拷贝文件的地址集
for p in path_joint_list:
    file_list =  os.listdir(p)
    for f in file_list:
        if 'source' in f:
            file_joint_list.append(p+"\\"+f)
print(file_joint_list)
file_get_list = []
for f in file_joint_list:
    filename_list = os.listdir(f)
    for filename in filename_list:
        if "doc" in filename:
            file_get_list.append(f+"\\"+filename)
j = "1"
for i in file_get_list:
    # print(os.path.isfile(i))
    shutil.copy(i, 'G:\java教程\\'+j+'.doc')
    j = int(j)
    j += 1
    j = str(j)

 删除文件的最后一行

# Tools:Pycharm 2017.3.2
# author ="wlx"
__date__ = '2018/8/12 20:37'
from collections import deque
deq = deque(maxlen=5)
print(deq.__len__())
with open('02第二模块之三体语录', 'r+', encoding='utf-8') as f:
    with open('new', 'w', encoding='utf-8') as f1:
        while True:
            line = f.readline()
            if line:
                deq.append(line)
                if deq.__len__() == 5:
                    f1.write(deq[0])
            else:
                break
        for i in range(3):
            f1.write(deq[i+1])

 读取文件最后一行

# Tools:Pycharm 2017.3.2
# author ="wlx"
__date__ = '2018/8/13 11:03'
'''
f_name为所读xx.txt文件
输出为:文件最后一行
'''

fname = 'test.txt'
with open(fname, 'r') as f:  # 打开文件
    first_line = f.readline()  # 读第一行
    off = -50  # 设置偏移量
    while True:
        f.seek(off, 2)  # seek(off, 2)表示文件指针:从文件末尾(2)开始向前50个字符(-50)
        lines = f.readlines()  # 读取文件指针范围内全部行
        if len(lines) >= 2:  # 判断是否最后至少有两行,这样保证了最后一行是完整的
            last_line = lines[-1]  # 取最后一行
            break
        # 若是off为50时获得的readlines只有一行内容,那么不能保证最后一行是完整的
        # 因此off翻倍从新运行,直到readlines不止一行
        off *= 2

print('文件' + fname + '第一行为:' + first_line)
print('文件' + fname + '最后一行为:' + last_line)

 实现对文件结束符(EOF)的判断

法一:用sys.stdin

import sys 
for line in sys.stdin: 
    a=int(line) 
    if a!=0: 
        print(a)

法二:用try…except

try:
    while True:
        s = input()
except EOFError:
    pass