• 五、IO编程


    input/output:输入、输出

    Stream(流):Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。(流:相当于管道)

    由于CPU和内存的速度远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。例如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,磁盘要接收这100M数据可能需要10秒,所以存在两种模式:

    1. 同步IO:CPU等着,程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行
    2. 异步IO:CPU不等待,继续执行后续代码,后续再回来接收。(较复杂)

    一、文件读写

    • 文件处理流程
    1. open()函数打开文件,得到文件句柄并赋值(不在同一路径下的需加 .py)
    2. 通过句柄对文件进行操作 (文件句柄相当于下文的 f )
    3. close()函数关闭文件
    • 文件打开模式
      • 读操作:解码默认GBK; open() 函数还可接收 errors 参数,可用  errors=ignore  忽略编码错误。
        1 r:只读,w:只写 ,a:追加
        2 f = open('文件名','权限',encoding='utf-8')    #传入需要打开的文件名并进行解码
        3 data = f.read() #查看文件
        4 print(date)
        5 f.close()   #关闭文件
         1 f = open('测试文件','r',encoding='utf-8')
         2 # date = f.read()
         3 # print(date)               #文件只打印一次,后面再打印不显示内容
         4 # print(f.readable())       #判断权限
         5 # print(f.readline())       #打印一行,没内容即不打印
         6 print(f.readlines())        #将文件内容每段以字符串的方式显示出来,并存在一个列表中
         7 f.close()
         8 
         9 输出:
        10 ['11111111111
        ', '22222222222
        ', '33333333333']
      • 写操作:直接新建空文档覆盖原来的文档

        1 f = open('测试文件','w',encoding='utf-8')
        2 f.write('1111
        ')
        3 f.writelines(['111','222']) #以列表的方式写入,内容只能是字符串
        4 f.writable()
        5 f.close()
      • 追加操作:将内容写到文件最后,不覆盖文件内容
      • r+:可读可写;w+a+x+。
        1 f = open('测试文件','r+',encoding='utf-8')
        2 f.write('内容')   #将内容覆盖到测试文件的开头,根据占用的字节进行替换
      • with...as...:可不用  close() 关闭文件
        1 #可使用with..as..:来打开或修改文件,不需要用close关闭。
        2 with open('测试文件','r',encoding='utf-8') as arc_f,/    #字符太长使用‘/‘进行换行处理
        3         open('新文件','w',encoding='utf-8') as dst_f:
      • 修改文件上的内容
        1 #查看文件内容并赋值到date上
        2 src_f = open('测试文件','r',encoding='utf-8')
        3 date = src_f.readline()
        4 src_f.close()
        5 #修改date索引位置的内容
        6 dst_f = open('测试文件','w',encoding='utf-8')
        7 dst_f.writelines(date[0])
        8 dst_f.close()
      • rb、wb、ab:可用于读取二进制文件,比如图片、视频等,不能指定编码(Windows下的换行为 ,Linux为 。 编码后再加 " newline=‘ ' ”读取文件真正换行符: )
      1. 转成二进制:字符串 -----》encode(编码)-----》》bytes
      2. 查看二进制:bytes -----》decode(解码)-----》》字符串
        1 #使用 rb 进行查看,返回二进制数
        2 f = open('test1.py','rb')
        3 date = f.read()
        4 print(date)
        5 f.close()
        6 
        7 输出:
        8 b'11111
        xe4xbdxa0xe5xa5xbd
        ' 
        1 #使用 wb 新建文件或写入内容,需进行编码
        2 f = open('test1.py','wb')
        3 date = f.write('1234
        你好'.encode('utf-8'))
        4 4# date = f.write(bytes('1234
        你好',encoding='utf-8'))
        5 f.close()
      • flush():刷新文件
      • seek():里面加数字,表示文件光标移动多少个字节(一个汉字占用三个字节,排除第一个汉字时为:文件句柄.seek(3),默认为: 文件句柄.seek(3,0) )
        • 文件句柄.seek(3,1)表示相对位置,即从上一个移到的位置接着往下移动;文件句柄.seek(-3,2)表示光标从后往前的位置。
      • read():文件句柄.read(1)表示读取文件一个位置的内容,汉字占用三个字节也用一个表示。与其它方法的表示不一样
      • truntruncate():加数字表示截取文件多少个字节的内容。需以写的方式打开,w与w+除外。
         1 #使用seek倒查文件最后一行
         2 f = open('test.txt', 'rb')
         3 for i in f:  # 使用for i in f 系统不会把所有数据读到内存中,而是需要读取时再读
         4     offs = -10  # 定义一个偏移量,因为倒查,所以为负数
         5     while True:
         6         f.seek(offs, 2)  # 
         7         data = f.readlines()  # 使用readlines(),会得到一个光标所在位置到结尾所有行的一个列表
         8         if len(data) > 1:  # 当列表大于1时,说明已取到完整的最后一行
         9             print(data[-1].decode('utf-8'))
        10             break
        11         offs *= 2  # 如果得到的列表不大于1,说明最后一行得到了一部分,就把偏移量*2,再进行循环

    二、StringIO和BytesIO

    • StringIO:在内存中读、写str,可先用一个str 初始化内容
       1 #读取StringIO内的文件
       2 from io import StringIO
       3 f = StringIO('hello
      hi
      goodbye')    
       4 while True:
       5     s = f.readline()
       6     if s == '':
       7         break
       8     print(s.strip())
       9 
      10 输出:
      11 hello
      12 hi
      13 goodbye
       1 #将字符串写入StringIO
       2 from io import StringIO
       3 f = StringIO()
       4 date = f.write('hello')
       5 f.write(' ')
       6 f.write('world!')
       7 print(date)
       8 print(f.getvalue()) #getvalue 获取写入后的字符串
       9 
      10 输出:
      11 5
      12 hello world!
    • BytesIO:在内存中读、写二进制数据
       1 #将bytes写入BytesIO
       2 from io import BytesIO
       3 f = BytesIO()
       4 date = f.write('中文'.encode('utf-8'))    #需将str经过utf-8编码为bytes
       5 print(date)
       6 print(f.getvalue())
       7 
       8 输出:
       9 6
      10 b'xe4xb8xadxe6x96x87'

    三、操作文件和目录

    • 使用os模块可直接调用操作系统提供的接口函数
      1 import os
      2 print(os.name)
      3 
      4 输出:
      5 nt

      如果是posix,说明系统是LinuxUnixMac OS X,如果是nt,就是Windows系统; uname() 函数可查看详细系统信息,Windows上不提供该函数;

    • 环境变量:保存在os.environ变量中,获取某个变量的值可用 os.environ,get('key’) 进行调用;
    • 文件操作:使用 os.path.join() 函数将两个路径合并,可处理不同操作系统的分割符( Windows: ;Linux:/ 
      1 import os
      2 d = os.path.abspath('.')    #查看当前目录的绝对路径
      3 #os.path.join('/Users/michael', 'testdir') #在Linux下创建;
      4 os.path.join('C:\Users\F·iy\Desktop','testdir') #创建新目录,先表示出新目录的完整路径;
      5 os.mkdir('C:\Users\F·iy\Desktop\testdir')   #创建目录
      6 os.rmdir('C:\Users\F·iy\Desktop\testdir')   #删除目录

      使用 os.path.split() 函数对路劲拆分为两部分,后部分为最后的文件目录或文件名; os.path.splitext() 函数可得到文件扩展名; os.rename() 对文件重命名

      1 os.path.split('C:\Users\F·iy\Desktop\testdir')
      2 os.path.splitext('test.py')         #得到('test', '.py')
      3 os.rename('test.txt','test.py')     #将.txt改为.py文件
      4 os.remove('test.py')                #删掉文件
      1 #列出当前目录下的所有文件
      2 a = [x for x in os.listdir('.') if os.path.isdir(x)]
      3 #列出所有的.py文件
      4 b = [x for x in os.listdir('.') if os.path.splitext(x)[1]=='.py']
      5 print(a,b)
      6 
      7 输出:
      8 ['__pycache__']   ['func.py', 'test.py', '__init__.py']

    四、序列化

      把变量从内存中变成可存储或传输的过程;(特定的序列化称为pickling)

      序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

      反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

     1 #使用pickle.dump()与pickle.load()
     2 
     3 import pickle
     4 d = dict(name='jack',age=18)
     5  #直接把对象序列化后写入一个file-like Object(one.txt)里;
     6 f = open('one.txt','wb')
     7 pickle.dump(d,f)
     8 f.close()
     9 #从一个file-like Object里直接反序列化出对象
    10 f = open('one.txt','rb')
    11 d = pickle.load(f)
    12 print(d)
    13 
    14 输出:
    15 {'name': 'jack', 'age': 18}
     1 #使用pickle.dumps() 与pickle.loads()
     2 
     3 import pickle
     4 d = dict(name='jack',age=18)
     5 a = pickle.dumps(d)     #把任意对象序列化成一个bytes
     6 b = pickle.loads(a)     #反序列化出对象
     7 print(a)
     8 print(b)
     9 
    10 输出:
    11 b'x80x03}qx00(Xx04x00x00x00nameqx01Xx04x00x00x00jackqx02Xx03x00x00x00ageqx03Kx12u.'
    12 {'name': 'jack', 'age': 18}
    • JSON:序列化的标准格式  json模块  更通用、更符合web标准。
       1 #使用json.dumps()与json.loads()
       2 
       3 import json
       4 d = dict(name='Bob', age=20, score=88)
       5 a = json.dumps(d)   #直接返回一个str
       6 b = json.loads(a)    #反序列化
       7 print(a)
       8 print(b)
       9 
      10 输出:
      11 {"name": "Bob", "age": 20, "score": 88}
      12 {'name': 'Bob', 'age': 20, 'score': 88}    
       1 import json
       2 d = dict(name='Bob', age=20)
       3 #创建文件
       4 f = open('text.txt','w')
       5 json.dump(d,f)
       6 #反序列化
       7 f = open('text.txt','r')
       8 b = json.load(f)
       9 print(b)
      10 
      11 输出:
      12 {'name': 'Bob', 'age': 20
    • 序列化 class 类,先将其转化为  dict  形式,使用 default 转换为可序列对象;反序列化时用 loads() 转换出一个dict对象后,使用 object_hook负责把 dict 转换为 Student 实例 
       1 import json
       2 
       3 class Student(object):
       4     def __init__(self, name, age, score):
       5         self.name = name
       6         self.age = age
       7         self.score = score
       8 
       9     def get(self):
      10         return '%s age is %s ,score:%s'% (self.name,self.age,self.score)
      11 #为class写一个转换函数
      12 def student_dict(std):
      13         return {
      14             'name': std.name,
      15             'age': std.age,
      16             'score': std.score
      17         }
      18 
      19 s = Student('jack', 18, 90)
      20 a = json.dumps(s, default=student_dict) #可选参数default可把任意一个对象变成一个可序列为JSON的对象
      21 #将class的实例变为dict,通常class的实例都有一个__dict__属性
      22 # print(json.dumps(s, default=lambda obj: obj.__dict__))
      23 print(a)
      24 
      25 #反序列化为class类的对象实例,先转换为dict后再转为实例
      26 def dict_student(d):
      27     return Student(d['name'], d['age'], d['score'])
      28 b = json.loads(a,object_hook=dict_student)
      29 print(b)    #实例对象
      30 print(b.get())  
      31 
      32 输出:
      33 {"name": "jack", "age": 18, "score": 90}
      34 <__main__.Student object at 0x000000B529F2C908>
      35 jack age is 18 ,score:90
  • 相关阅读:
    设置Tomcat根目录
    使用Servlet Filter做Login checking
    Javac命令一次编译一个目录下的所有java文件
    Java ArrayList操作
    Java 读Properties
    Java文件读写
    Servlet Listener
    Servlet连接数据库
    Servlet Filter 3
    Servlet Filter 2
  • 原文地址:https://www.cnblogs.com/liqiongming/p/10085342.html
Copyright © 2020-2023  润新知