StringIO
很多時候,數據讀寫不一定是文件,也可以在內存中讀寫。
要把str寫入StringIO,我們需要先創建一個StringIO,然后像文件一樣寫入即可
>>> from io import StringIO >>> f=StringIO() >>> f.write('hello') 5 >>> f.write(' ') 1 >>> f.write('world!') 6 >>> f <_io.StringIO object at 0x7f6bbc76e318> >>> f.getvalue() 'hello world!'
getvalue()方法用於獲得寫入后的str
要讀取StringIO,可以用一個str初始化StringIO,然后像讀文件一樣讀取
>>> f=StringIO('Hello!\nHi!\nGoodbye!') >>> while True: ... s=f.readline() ... if s=='': ... break ... print(s.strip()) ... Hello! Hi! Goodbye!
BytesIO
StringIO操作的只能是str,如果要操作二進制數據,就需要使用BytesIO。
BytesIO實現了在內存中讀寫bytes,我們創建一個BytesIO,然后寫入一些bytes:
>>> from io import BytesIO >>> f=BytesIO() >>> f.write('中文'.encode('utf-8')) 6 >>> f.getvalue() b'\xe4\xb8\xad\xe6\x96\x87'
請注意,寫入的不是str,而是經過UTF-8編碼的bytes。
和StringIO類似,可以用一個bytes初始化BytesIO,然后,像讀文件一樣讀取:
>>> from io import BytesIO >>> f=BytesIO(b'\xe4\xb8\xad\xe6\x96\x87') >>> f.read() b'\xe4\xb8\xad\xe6\x96\x87'
StringIO和BytesIO是在內存中操作str和bytes的方法,使得和讀寫文件具有一致的接口。
用一個列子加深對StringIO和BytesIO的理解
# StringIO和BytesIO # stringIO 比如說,這時候,你需要對獲取到的數據進行操作,但是你並不想把數據寫到本地硬盤上,這時候你就可以用stringIO from io import StringIO from io import BytesIO def outputstring(): return 'string \nfrom \noutputstring \nfunction' s = outputstring() #s為字符串'string \nfrom \noutputstring \nfunction' #將函數返回的數據在內存中讀 sio=StringIO(s) #可以用StringIO本身的方法 sio.getvalue() #輸出 #'string \nfrom \noutputstring \nfunction' #也可以用file-like object的方法 s=sio.readlines() #readlines返回的是一個列表 #['string \n', 'from \n', 'outputstring \n', 'function'] for i in s: print(i.strip()) #去除尾部的回車符號輸出 #string #from #outputstring #function #將函數返回的數據在內存中寫 s=outputstring() sio=StringIO() sio.write(s) #如果是在終端會顯示指針位置值36 #可以用StringIO本身的方法查看 print(sio.getvalue()) #如果你用file-like object的方法查看的時候,你會發現數據為空 #因為指針位置在尾部36 for i in sio.readlines(): print(i.strip()) #這時候我們需要修改下文件的指針位置 #就可以打印內容了 sio.seek(0,0) #打印指針位置 print(sio.tell()) #結果為0 # 這就涉及到了兩個方法seek 和 tell # tell 方法獲取當前文件讀取指針的位置 # seek 方法,用於移動文件讀寫指針到指定位置,有兩個參數,第一個offset: 偏移量,需要向前或向后的字節數,正為向后,負為向前;第二個whence: 可選值,默認為0,表示文件開頭,1表示相對於當前的位置,2表示文件末尾 # 用seek方法時,需注意,如果你打開的文件沒有用'b'的方式打開,則offset無法使用負值哦 #在使用file-like object方法可以打印了 for i in sio.readlines(): print(i.strip()) # stringIO 只能操作str,如果要操作二進制數據,就需要用到BytesIO # 上面的sio無法用seek從當前位置向前移動,這時候,我們用'b'的方式寫入數據,就可以向前移動了 bio=BytesIO() bio.write(s.encode('utf-8')) #使用getvalue()方法quzhi print(bio.getvalue()) #b'string \nfrom \noutputstring \nfunction' #修改指針 #1代表從當前位置,-36代表往前移動36 bio.seek(-36,1) bio.tell() #0 for i in bio.readlines(): print(i.strip())
注意:當使用StringIO去初始化的時候,其指針是指向0的位置,而如果是用write的方法的時候,其指針會移動到最后
舉例如下
>>> sio=StringIO('abc') >>> sio.getvalue() 'abc' >>> sio.tell() 0 #初始化指針指向0 值為'abc' >>> sio=StringIO('def') >>> sio.tell() 0 >>> sio.getvalue() 'def' #再次初始化會覆蓋原值
對比write方法
>>> a=StringIO() #寫指針加3 >>> a.write('123') 3 #再次寫追加指針再加3 >>> a.write('456') 3 #值為追加非覆蓋 >>> a.getvalue() '123456' #最后指針為6 >>> a.tell() 6