5-Python-文件操作、异常、模块

来源:互联网 发布:南风知我意琰阙 编辑:程序博客网 时间:2024/05/16 14:37
  1. 知识点
    1. 知识点
    2. --Python-文件操作、异常、模块

  2. 文件操作
    1. <1>打开文件
    2. python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
      1. open(文件名,访问模式)
      示例如下:

    3. f = open('test.txt', 'w')

    4. 说明:
    5. 访问模式说明r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。w打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。wb以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。r+打开一个文件用于读写文件指针将会放在文件的开头。w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。wb+以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

    1. <2>关闭文件
    2. close( )
    3. 示例如下:
    4. # 新建一个文件,文件名为:test.txt
    5. f = open('test.txt', 'w')
    6. # 关闭这个文件
    7. f.close()

  3. 文件的读写
    1. 文件的读写
    2. <1>写数据(write)
    3. 使用write()可以完成向文件写入数据
    4. demo:
    5. f = open('test.txt', 'w')
    6. f.write('hello world, i am here!')
    7. f.close()
    8. 运行现象:
    1. <2>读数据(read)
    2. 使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度单位是字节),如果没有传入num,那么就表示读取文件中所有的数据
    3. demo:
    4. f = open('test.txt', 'r')
    5. content = f.read(5)
    6. print(content)
    7. print("-"*30)
    8. content = f.read()
    9. print(content)
    10. f.close()
    11. 运行现象:
    1. <3>读数据(readlines
    2. 就像read没有参数时一样,readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行的数据为一个元素
    3. #coding=utf-8
    4. f = open('test.txt', 'r')
    5. content = f.readlines()
    6. print(type(content))
    7. i=1
    8. for temp in content:
    9. print("%d:%s"%(i, temp))
    10. i+=1
    11. f.close()
    12. 运行现象:
    1. <4>读数据(readline
    2. #coding=utf-8
    3. f = open('test.txt', 'r')
    4. content = f.readline()
    5. print("1:%s"%content)
    6. content = f.readline()
    7. print("2:%s"%content)
    8. f.close()
    1. 想一想:
    2. 如果一个文件很大,比如5G,试想应该怎样把文件的数据读取到内存然后进行处理呢?

  4. 应用1:制作文件的备份
    1. 任务描述
    2. 输入文件的名字,然后程序自动完成对文件进行备份
    3. 参考代码
      1. #coding=utf-8
      2. oldFileName = raw_input("请输入要拷贝的文件名字:")
      3. oldFile = open(oldFileName,'rb')
      4. # 如果打开文件
      5. if oldFile:
      6. # 提取文件的后缀
      7. fileFlagNum = oldFileName.rfind('.')
      8. if fileFlagNum > 0:
      9. fileFlag = oldFileName[fileFlagNum:]
      10. # 组织新的文件名字
      11. newFileName = oldFileName[:fileFlagNum] + '[复件]' + fileFlag
      12. # 创建新文件
      13. newFile = open(newFileName, 'wb')
      14. # 把旧文件中的数据,一行一行的进行复制到新文件中
      15. for lineContent in oldFile.readlines():
      16. newFile.write(lineContent)
      17. # 关闭文件
      18. oldFile.close()
      19. newFile.close()


  5. 文件的定位读写
    1. <1>获取当前读写的位置
    2. 在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取
      1. # 打开一个已经存在的文件
      2. f = open("test.txt", "r")
      3. str = f.read(3)
      4. print "读取的数据是 : ", str
      5. # 查找当前位置
      6. position = f.tell()
      7. print "当前文件位置 : ", position
      8. str = f.read(3)
      9. print "读取的数据是 : ", str
      10. # 查找当前位置
      11. position = f.tell()
      12. print "当前文件位置 : ", position
      13. f.close()

    3. <2>定位到某个位置
    4. 如果在读写文件的过程中,需要从另外一个位置进行操作的话,可以使用seek()
      1. seek(offset, from)有2个参数
      2. offset:偏移量
      3. from:方向
      4. 0:表示文件开头
      5. 1:表示当前位置
      6. 2:表示文件末尾
      demo:把位置设置为:从文件开头,偏移5个字节
      1. # 打开一个已经存在的文件
      2. f = open("test.txt", "r")
      3. str = f.read(30)
      4. print "读取的数据是 : ", str
      5. # 查找当前位置
      6. position = f.tell()
      7. print "当前文件位置 : ", position
      8. # 重新设置位置
      9. f.seek(5,0)
      10. # 查找当前位置
      11. position = f.tell()
      12. print "当前文件位置 : ", position
      13. f.close()
      demo:把位置设置为:离文件末尾,3字节处
      1. # 打开一个已经存在的文件
      2. f = open("test.txt", "r")
      3. # 查找当前位置
      4. position = f.tell()
      5. print "当前文件位置 : ", position
      6. # 重新设置位置
      7. f.seek(-3,2)
      8. # 读取到的数据为:文件最后3个字节数据
      9. str = f.read()
      10. print "读取的数据是 : ", str
      11. f.close()


  6. 文件重命名、删除
    1. 有些时候,需要对文件进行重命名、删除等一些操作,pythonos模块中都有这么功能
    2. <1>文件重命名
    3. os模块中的rename()可以完成对文件的重命名操作
    4. rename(需要修改的文件名, 新的文件名)
      1. import os
      2. os.rename("毕业论文.txt", "毕业论文-最终版.txt")

    5. <2>删除文件
    6. os模块中的remove()可以完成对文件的删除操作
    7. remove(待删除的文件名)
      1. import os
      2. os.remove("毕业论文.txt")


  7. 文件夹的相关操作
    1. 文件夹的相关操作
    2. 实际开发中,有时需要用程序的方式对文件夹进行一定的操作,比如创建、删除等
    3. 就像对文件操作需要os模块一样,如果要操作文件夹,同样需要os模块
    4. <1>创建文件夹
      1. import os
      2. os.mkdir("张三")
      <2>获取当前目录
      1. import os
      2. os.getcwd()
      <3>改变默认目录
      1. import os
      2. os.chdir("../")
      <4>获取目录列表
      1. import os
      2. os.listdir("./")
      <5>删除文件夹
      1. import os
      2. os.rmdir("张三")

  8. 应用2:批量修改文件名
    1. 应用:批量修改文件名
    2. <1>运行过程演示
    3. 运行程序之前
    4. 运行程序之后
    5. <2>参考代码
      1. #coding=utf-8
      2. # 批量在文件名前加前缀
      3. import os
      4. funFlag = 1 # 1表示添加标志 2表示删除标志
      5. folderName = './renameDir/'
      6. # 获取指定路径的所有文件名字
      7. dirList = os.listdir(folderName)
      8. # 遍历输出所有文件名字
      9. for name in dirList:
      10. print name
      11. if funFlag == 1:
      12. newName = '[东哥出品]-' + name
      13. elif funFlag == 2:
      14. num = len('[东哥出品]-')
      15. newName = name[num:]
      16. print newName
      17. os.rename(folderName+name, folderName+newName)


  9. 异常介绍
    1. 异常
    2. <1>异常简介
    3. 看如下示例:
      1. print '-----test--1---'
      2. open('123.txt','r')
      3. print '-----test--2---'

    4. 运行结果:


    5. 说明:
      1. 打开一个不存在的文件123.txt,当找不到123.txt 文件时,就会抛出给我们一个IOError类型的错误,No such file or directory123.txt (没有123.txt这样的文件或目录)

    6. 异常:
      1. Python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"


  10. 捕获异常
    1. 案例剖析
    2. <1>捕获异常 try...except...
    3. 看如下示例:
      1. try:
      2. print '-----test--1---'
      3. open('123.txt','r')
      4. print '-----test--2---'
      5. except IOError:
      6. pass

    4. 运行结果:

    5. 说明:
      1. 此程序看不到任何错误,因为用except 接收了产生IOError错误,并添加了处理错误的方法
      2. pass 表示实现了相应的实现,但什么也不做;如果把pass改为print语句,那么就会输出其他信息

    6. 小总结:

    7. <2>获取异常的信息描述
    8. 看如下示例:
      1. try:
      2. print num
      3. except IOError:
      4. print '产生错误了;'

    9. 运行结果如下:

    10. 想一想:
      1. 上例程序,已经使用except来捕获异常了,为什么还会看到错误的信息提示?
    11. 答:
      1. except捕获的错误类型是IOError,而此时程序产生的异常为 NameError ,所以except没有生效

    12. 修改后的代码为:
      1. try:
      2. print num
      3. except NameError:
      4. print '产生错误了;'

    13. 运行结果如下:

    14. 想一想:
      1. 上例程序中,已经能够捕获到异常了,那么这个NameError异常,有没有一些信息描述呢?那又该怎样查看?

    15. 答:
      1. 接收错误类型的后面定义一个变量(例如:errorMsg)用于接收具体错误信息, 然后将接收的错误信息打印即可

    16. 修改后的代码为:
      1. try:
      2. print num
      3. except NameError, errorMsg:
      4. print '产生错误了;', errorMsg

    17. 运行结果如下:

    18. <3> except捕获多个异常
      1. #coding=utf-8
      2. try:
      3. print '-----test--1---'
      4. # 如果123.txt文件不存在,那么会产生 IOError 异常
      5. open('123.txt','r')
      6. print '-----test--2---'
      7. # 如果num变量没有定义,那么会产生 NameError 异常
      8. print num
      9. except (IOError,NameError), errorMsg:
      10. #如果想通过一次except捕获到多个异常可以用一个元组的方式
      11. # errorMsg里会保存捕获到的错误信息
      12. print errorMsg

    19. 注意:
      1. 如果想捕获所有的异常,可以省略 except后面的变量
      2. 但是这种方法不建议大家使用,会隐藏一些开发者没有想到的异常情况

    20. <4> try...finally...
    21. try...finally...语句用来表达这样的情况
      1. 不管线捕捉到的是什么错误,无论错误是不是发生,这些代码“必须”运行,比如文件关闭,释放锁,把数据库连接返还给连接池等

    22. demo:
      1. import time
      2. try:
      3. f = file('poem.txt')
      4. while True: # our usual file-reading idiom
      5. line = f.readline()
      6. if len(line) == 0:
      7. break
      8. time.sleep(2)
      9. print line,
      10. finally:
      11. f.close()
      12. print 'Cleaning up...closed the file'

    23. 说明:
      1. 程序读poem.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl-c中断/取消程序。
      2. 我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。

    24. <4> else
    25. 咱们应该对else并不陌生,在if中,它的作用是当条件不满足时执行的实行;同样在try...except...中也是如果,即如果没有捕获到异常,那么就执行else中的事情
      1. try:
      2. num = 100
      3. print num
      4. except NameError, errorMsg:
      5. print('产生错误了:%s'%errorMsg)
      6. else:
      7. print('没有捕获到异常,真高兴')
      8. finally:
      9. print('我一定会执行的哦')


    26. 运行结果如下:


  11. 抛出异常
    1. 抛出异常
    2. 你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是ErrorException类的子类
    3. 下面是一个引发异常的例子:
      1. class ShortInputException(Exception):
      2. '''你定义的异常类。'''
      3. def __init__(self, length, atleast):
      4. Exception.__init__(self)
      5. self.length = length
      6. self.atleast = atleast
      7. try:
      8. s = raw_input('请输入 --> ')
      9. if len(s) < 3:
      10. # raise引发一个你定义的异常
      11. raise ShortInputException(len(s), 3)
      12. except EOFError:
      13. print '/n你输入了一个结束标记EOF'
      14. except ShortInputException, x:#x这个变量被绑定到了错误的实例
      15. print('ShortInputException: 输入的长度是 %d,长度至少应是 %d'% (x.length, x.atleast))
      16. else:
      17. print '没有异常发生.'

    4. 运行结果如下:
      1. $ python raising.py
      2. 请输入 -->
      3. 你输入了一个结束标记EOF
      4. $ python raising.py
      5. 请输入 --> --> ab
      6. ShortInputException: 输入的长度是 2, 长度至少应是 3
      7. $ python raising.py
      8. 请输入 --> abc
      9. 没有异常发生.



  12. 模块介绍
    1. <1>Python中的模块
    2. 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include"引入math.h这个头文件,否则是无法正常进行调用的。那么在Python中,如果要引用一些内置的函数,该怎么处理呢?
    3. Python中有一个概念叫做模块(module),这个和C语言中的头文件以及Java中的包很类似,比如在Python中要调用sqrt函数,必须用import关键字引入math这个模块,下面就来了解一下Python中的模块。
    4. 说的通俗点:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块
    5. <2>import
    6. Python中用关键字import来引入某个模块,比如要引用模块math,就可以在文件最开始的地方用import math来引入。
    7. 形如:
      1. import module1,mudule2...


    8. 当解释器遇到import语句,如果模块在当前的搜索路径就会被导入。
    9. 在调用math模块中的函数时,必须这样引用:
    10.   
      1. 模块名.函数名


    11. 想一想:
    12. 为什么必须加上模块名这样调用呢?
    13. 答:
    14. 因为可能存在这样一种情况:在多个模块中含有相同名称的函数,此时如果只是通过函数名来调用,解释器无法知道到底要调用哪个函数。所以如果像上述这样引入模块的时候,调用函数必须加上模块名
      1. 模块名.函数名

    15. 有时候我们只需要用到模块中的某个函数,只需要引入该函数即可,此时可以以下方法实现
      1. from 模块名 import 函数名1,函数名2....

    16. 不仅可以引入函数,还可以引入一些变量
    17. 注意:
    18. 通过这种方式引入的时候,调用函数时只能给出函数名,不能给出模块名,但是当两个模块中含有相同名称函数的时候,后面一次引入会覆盖前一次引入。也就是说假如模块A中有函数function( ),在模块B中也有函数function( ),如果引入A中的function在先、B中的function在后,那么当调用function函数的时候,是去执行模块B中的function函数。
    19. 如果想一次性引入math中所有的东西,还可以通过from math import *来实现,但是不建议这么做
    20. <3>fromimport

    21. Pythonfrom语句让你从模块中导入一个指定的部分到当前命名空间中。
    22. 语法如下:
      1. from modname import name1[, name2[, ... nameN]]

    23. 例如,要导入模块fibfibonacci函数,使用如下语句:
      1. from fib import fibonacci

    24. 这个声明不会把整个fib模块导入到当前的命名空间中,它只会将fib里的fibonacci单个引入
    25. <4>from import *
    26. 把一个模块的所有内容全都导入到当前的命名空间也是可行的,只需使用如下声明:
      1. from modname import *

    27. 这提供了一个简单的方法来导入一个模块中的所有项目。然而这种声明不该被过多地使用。
    28. <5>定位模块

    29. 当你导入一个模块,Python解析器对模块位置的搜索顺序是:
      1. 当前目录
      2. 如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
      3. 如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为/usr/local/lib/python/
      4. 模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。


  13. 模块制作
    1. <1>定义自己的模块
    2. Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。
    3. 比如有这样一个文件test.py,在test.py中定义了函数add
    4. test.py
      1. def add(a,b):
      2. return a+b

    5. <2>调用自己定义的模块
    6. 那么在其他文件中就可以先import test,然后通过test.add(a,b)来调用了,当然也可以通过from test import add来引入
    7. main.py
      1. import test
      2. result = test.add(11,22)
      3. print(result)

    8. <3>测试模块
    9. 在实际开中,有时一个模块,是一个开发人员进行编写,为了让整个模块中的功能都达到想要的效果,有时编程人员会自行在py文件中添加一些测试信息,例如:
    10. test.py
      1. def add(a,b):
      2. return a+b
      3. # 用来进行测试
      4. ret = add(12,22)
      5. print('int test.py file,,,,12+22=%d'%ret)

    11. 如果此时,在其他py文件中引入了此文件的话,想想看,测试的那段代码是否也会执行呢!
    12. main.py
      1. import test
      2. result = test.add(11,22)
      3. print(result)

    13. 运行现象:

    14. 至此,可发现test.py中的测试代码,应该是单独执行test.py文件时,才应该执行的,不应该是其他的文件中引用而执行
    15. 为了解决这个问题,python在执行一个文件时有个变量__name__



    16. 总结:
    17. 可以根据__name__变量的结果能够判断出,是直接执行的python脚本还是被引入执行的,从而能够有选择性的执行测试代码


  14. Python中的包
    1. python中的包
    2. 1.python中的包
    3. 包将有联系的模块组织在一起,有效避免模块名称冲突问题,让应用组织结构更加清晰
    4. 假定我们的包的例子有如下的目录结构:
      1. Phone/
      2. __init__.py
      3. common_util.py
      4. Voicedta/
      5. __init__.py
      6. Pots.py
      7. Isdn.py
      8. Fax/
      9. __init__.py
      10. G3.py
      11. Mobile/
      12. __init__.py
      13. Analog.py
      14. igital.py
      15. Pager/
      16. __init__.py
      17. Numeric.py

    5. Phone 是最顶层的包,Voicedta 等是它的子包。 我们可以这样导入子包:
      1. import Phone.Mobile.Analog
      2. Phone.Mobile.Analog.dial()

    6. 你也可使用 from-import 实现不同需求的导入
    7. 第一种方法是只导入顶层的子包,然后使用属性/点操作符向下引用子包树
      1. from Phone import Mobile
      2. Mobile.Analog.dial('555-1212')

    8. 此外,我们可以还引用更多的子包:
    9. from Phone.Mobile import Analog
    10. Analog.dial('555-1212')

    11. 事实上,你可以一直沿子包的树状结构导入:
      1. from Phone.Mobile.Analog import dial
      2. dial('555-1212')

    12. 在我们上边的目录结构中,我们可以发现很多的 __init__.py 文件。这些是初始化模块,from-import 语句导入子包时需要用到它。 如果没有用到,他们可以是空文件。
    13. 包同样支持 from-import all 语句
      1. from package.module import *

    14. 然而,这样的语句会导入哪些文件取决于操作系统的文件系统。所以我们在__init__.py 中加入 __all__ 变量。该变量包含执行这样的语句时应该导入的模块的名字。它由一个模块名字符串列表组成.。
    15. 2. __all__
    16. Pythonmoudle是很重要的一个概念moudle里一般都会有一个__init__.py文件。有的__init__.py中是空白,有的却会有__all__参数
    17. 如果其他页面import 的时候,如果__init__.py是空白的,可以直接importmoudle的所有函数。而如果__init__.py中定义了__all__,则import 的时候只会导入__all__部分定义的内容
    18. 例如,我们可以这样组织一个package:
      1. package1/
      2. __init__.py
      3. subPack1/
      4. __init__.py
      5. module_11.py
      6. module_12.py
      7. module_13.py
      8. subPack2/
      9. __init__.py
      10. module_21.py
      11. module_22.py

    19. __init__.py可以为空,只要它存在,就表明此目录应被作为一个package处理。当然,__init__.py中也可以设置相应的内容
    20. 现在我们在module_11.py中定义一个函数:
      1. def funA():
      2. print "funcA in module_11"

    21. 在顶层目录(也就是package1所在的目录,当然也参考上面的介绍,将package1放在解释器能够搜索到的地方)运行python:
      1. >>>from package1.subPack1.module_11 import funcA
      2. >>>funcA()
      3. funcA in module_11

    22. 这样,我们就按照package的层次关系,正确调用了module_11中的函数。
    23. 细心的同学会发现,有时在import语句中会出现通配符*,导入某个module中的所有元素,这是怎么实现的呢?
    24. 答案就在__init__.py中。我们在subPack1__init__.py文件中写
      1. __all__ = ['module_13', 'module_12']

    25. 然后进入python
      1. >>>from package1.subPack1 import *
      2. >>>module_11.funcA()
      3. Traceback (most recent call last):
      4. File "", line 1, in
      5. ImportError: No module named module_11

    26. 也就是说,以*导入时,package内的module是受__init__.py限制的

  15. 模块发布
    1. 模块发布
    2. 1.mymodule目录结构体如下:
      1. .
      2. ├── setup.py
      3. ├── suba
      4. ├── aa.py
      5. ├── bb.py
      6. └── __init__.py
      7. └── subb
      8. ├── cc.py
      9. ├── dd.py
      10. └── __init__.py

    3. 2.编写setup.py,py_modules需指明所需包含的py文件
      1. from distutils.core import setup
      2. setup(name="xwp", version="1.0", description="xwp's module", author="xingwenpeng", py_modules=['suba.aa', 'suba.bb', 'subb.cc', 'subb.dd'])

    4. 3.构建模块
      1. python setup.py build

    5. 构建后目录结构
      1. .
      2. ├── build
      3. └── lib.linux-i686-2.7
      4. ├── suba
      5. ├── aa.py
      6. ├── bb.py
      7. └── __init__.py
      8. └── subb
      9. ├── cc.py
      10. ├── dd.py
      11. └── __init__.py
      12. ├── setup.py
      13. ├── suba
      14. ├── aa.py
      15. ├── bb.py
      16. └── __init__.py
      17. └── subb
      18. ├── cc.py
      19. ├── dd.py
      20. └── __init__.py

    6. 4.生成发布压缩包
      1. python setup.py sdist

    7. 打包后,生成最终发布压缩包xwp-1.0.tar.gz , 目录结构
      1. .
      2. ├── build
      3. └── lib.linux-i686-2.7
      4. ├── suba
      5. ├── aa.py
      6. ├── bb.py
      7. └── __init__.py
      8. └── subb
      9. ├── cc.py
      10. ├── dd.py
      11. └── __init__.py
      12. ├── dist
      13. └── xwp-1.0.tar.gz
      14. ├── MANIFEST
      15. ├── setup.py
      16. ├── suba
      17. ├── aa.py
      18. ├── bb.py
      19. └── __init__.py
      20. └── subb
      21. ├── cc.py
      22. ├── dd.py
      23. └── __init__.py


  16. 作业
    1. 必做题
    2. 1. 编写程序,完成‘文件加密解密器’
    3. 思路提示(只有想不出来的时候,才可以看哦)
    4. 打开一个已经存在的文件(最好以二进制的方式打开)
    5. 创建一个文件(比如叫 xxx加密后.txt),用来写入要加密后的数据
    6. 使用循环 每次读取一行的方式,获取到数据
    7. 对第3步获取到的数据,每个字符的方式进行加密,并且写入到第2步创建好的文件中
    8. 关闭所有打开的文件