14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmr"""File-like objects that read from or write to a string buffer. 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis implements (nearly) all stdio methods. 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf = StringIO() # ready for writing 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf = StringIO(buf) # ready for reading 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.close() # explicitly release resources held 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmflag = f.isatty() # always false 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpos = f.tell() # get current position 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.seek(pos) # set current position 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuf = f.read() # read until EOF 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuf = f.read(n) # read up to n bytes 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmbuf = f.readline() # read until end of line ('\n') or EOF 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmlist = f.readlines()# list of f.readline() results until EOF 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.truncate([size]) # truncate file at to at most size (default: current pos) 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.write(buf) # write at current position 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.writelines(list) # for line in list: f.write(line) 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmf.getvalue() # return whole file's contents as a string 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmNotes: 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- Using a real file is often faster (but less convenient). 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- There's also a much faster implementation in C, called cStringIO, but 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm it's not subclassable. 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- fileno() is left unimplemented so that code which uses it triggers 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm an exception early. 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- Seeking far beyond EOF and then writing will insert real null 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm bytes that occupy space in the buffer. 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm- There's a simple test set (see end of this file). 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm""" 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmtry: 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm from errno import EINVAL 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmexcept ImportError: 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm EINVAL = 22 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm__all__ = ["StringIO"] 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef _complain_ifclosed(closed): 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if closed: 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise ValueError, "I/O operation on closed file" 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass StringIO: 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """class StringIO([buffer]) 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm When a StringIO object is created, it can be initialized to an existing 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm string by passing the string to the constructor. If no string is given, 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm the StringIO will start empty. 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The StringIO object can accept either Unicode or 8-bit strings, but 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm mixing the two may take some care. If both are used, 8-bit strings that 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm a UnicodeError to be raised when getvalue() is called. 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __init__(self, buf = ''): 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Force self.buf to be a string or unicode 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not isinstance(buf, basestring): 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm buf = str(buf) 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf = buf 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.len = len(buf) 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [] 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = 0 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.closed = False 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.softspace = 0 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def __iter__(self): 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def next(self): 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """A file object is its own iterator, for example iter(f) returns f 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (unless f is closed). When a file is used as an iterator, typically 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm in a for loop (for example, for line in f: print line), the next() 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm method is called repeatedly. This method returns the next input line, 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm or raises StopIteration when EOF is hit. 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = self.readline() 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not r: 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise StopIteration 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return r 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def close(self): 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Free the memory buffer. 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not self.closed: 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.closed = True 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm del self.buf, self.pos 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def isatty(self): 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Returns False because StringIO objects are not connected to a 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm tty-like device. 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return False 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def seek(self, pos, mode = 0): 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Set the file's current position. 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The mode argument is optional and defaults to 0 (absolute file 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm positioning); other values are 1 (seek relative to the current 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm position) and 2 (seek relative to the file's end). 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm There is no return value. 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buflist: 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf += ''.join(self.buflist) 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [] 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if mode == 1: 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pos += self.pos 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif mode == 2: 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pos += self.len 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = max(0, pos) 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def tell(self): 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Return the file's current position.""" 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self.pos 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def read(self, n = -1): 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Read at most size bytes from the file 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (less if the read hits EOF before obtaining size bytes). 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If the size argument is negative or omitted, read all data until EOF 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is reached. The bytes are returned as a string object. An empty 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm string is returned when EOF is encountered immediately. 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buflist: 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf += ''.join(self.buflist) 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [] 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if n is None or n < 0: 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = self.len 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = min(self.pos+n, self.len) 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = self.buf[self.pos:newpos] 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = newpos 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return r 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def readline(self, length=None): 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r"""Read one entire line from the file. 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm A trailing newline character is kept in the string (but may be absent 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm when a file ends with an incomplete line). If the size argument is 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm present and non-negative, it is a maximum byte count (including the 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm trailing newline) and an incomplete line may be returned. 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm An empty string is returned only when EOF is encountered immediately. 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Note: Unlike stdio's fgets(), the returned string contains null 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm characters ('\0') if they occurred in the input. 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buflist: 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf += ''.join(self.buflist) 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [] 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm i = self.buf.find('\n', self.pos) 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if i < 0: 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = self.len 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = i+1 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if length is not None and length > 0: 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.pos + length < newpos: 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = self.pos + length 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm r = self.buf[self.pos:newpos] 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = newpos 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return r 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def readlines(self, sizehint = 0): 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Read until EOF using readline() and return a list containing the 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines thus read. 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If the optional sizehint argument is present, instead of reading up 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm to EOF, whole lines totalling approximately sizehint bytes (or more 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm to accommodate a final whole line). 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm total = 0 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = [] 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = self.readline() 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while line: 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines.append(line) 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm total += len(line) 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if 0 < sizehint <= total: 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm break 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = self.readline() 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return lines 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def truncate(self, size=None): 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Truncate the file's size. 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If the optional size argument is present, the file is truncated to 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (at most) that size. The size defaults to the current position. 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The current file position is not changed unless the position 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is beyond the new file size. 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm If the specified size exceeds the file's current size, the 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm file remains unchanged. 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if size is None: 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm size = self.pos 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size < 0: 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise IOError(EINVAL, "Negative size not allowed") 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm elif size < self.pos: 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = size 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf = self.getvalue()[:size] 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.len = size 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def write(self, s): 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Write a string to the file. 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm There is no return value. 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not s: return 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm # Force s to be a string or unicode 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if not isinstance(s, basestring): 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm s = str(s) 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm spos = self.pos 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm slen = self.len 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if spos == slen: 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist.append(s) 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.len = self.pos = spos + len(s) 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if spos > slen: 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist.append('\0'*(spos - slen)) 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm slen = spos 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm newpos = spos + len(s) 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if spos < slen: 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buflist: 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf += ''.join(self.buflist) 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [self.buf[:spos], s, self.buf[newpos:]] 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf = '' 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if newpos > slen: 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm slen = newpos 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist.append(s) 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm slen = newpos 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.len = slen 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.pos = newpos 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def writelines(self, iterable): 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Write a sequence of strings to the file. The sequence can be any 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm iterable object producing strings, typically a list of strings. There 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is no return value. 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (The name is intended to match readlines(); writelines() does not add 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line separators.) 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm write = self.write 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for line in iterable: 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm write(line) 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def flush(self): 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """Flush the internal buffer 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm def getvalue(self): 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Retrieve the entire contents of the "file" at any time before 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm the StringIO object's close() method is called. 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm The StringIO object can accept either Unicode or 8-bit strings, 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm but mixing the two may take some care. If both are used, 8-bit 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm strings that cannot be interpreted as 7-bit ASCII (that use the 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 8th bit) will cause a UnicodeError to be raised when getvalue() 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm is called. 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm """ 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm _complain_ifclosed(self.closed) 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if self.buflist: 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buf += ''.join(self.buflist) 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self.buflist = [] 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return self.buf 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm# A little test suite 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdef test(): 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm import sys 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if sys.argv[1:]: 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm file = sys.argv[1] 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm else: 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm file = '/etc/passwd' 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm lines = open(file, 'r').readlines() 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm text = open(file, 'r').read() 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f = StringIO() 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm for line in lines[:-2]: 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.write(line) 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.writelines(lines[-2:]) 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if f.getvalue() != text: 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, 'write failed' 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm length = f.tell() 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'File length =', length 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(len(lines[0])) 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.write(lines[1]) 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(0) 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'First line =', repr(f.readline()) 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'Position =', f.tell() 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = f.readline() 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'Second line =', repr(line) 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(-len(line), 1) 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line2 = f.read(len(line)) 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if line != line2: 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, 'bad result after seek back' 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(len(line2), 1) 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm list = f.readlines() 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line = list[-1] 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(f.tell() - len(line)) 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm line2 = f.read() 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if line != line2: 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, 'bad result after seek back from EOF' 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'Read', len(list), 'more lines' 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'File length =', f.tell() 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if f.tell() != length: 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, 'bad length' 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.truncate(length/2) 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.seek(0, 2) 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm print 'Truncated length =', f.tell() 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if f.tell() != length/2: 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm raise RuntimeError, 'truncate did not adjust length' 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm f.close() 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmif __name__ == '__main__': 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm test() 325