0001 r"""File-like objects that read from or write to a string buffer. 0002 0003 This implements (nearly) all stdio methods. 0004 0005 f = StringIO() # ready for writing 0006 f = StringIO(buf) # ready for reading 0007 f.close() # explicitly release resources held 0008 flag = f.isatty() # always false 0009 pos = f.tell() # get current position 0010 f.seek(pos) # set current position 0011 f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF 0012 buf = f.read() # read until EOF 0013 buf = f.read(n) # read up to n bytes 0014 buf = f.readline() # read until end of line ('\n') or EOF 0015 list = f.readlines()# list of f.readline() results until EOF 0016 f.truncate([size]) # truncate file at to at most size (default: current pos) 0017 f.write(buf) # write at current position 0018 f.writelines(list) # for line in list: f.write(line) 0019 f.getvalue() # return whole file's contents as a string 0020 0021 Notes: 0022 - Using a real file is often faster (but less convenient). 0023 - There's also a much faster implementation in C, called cStringIO, but 0024 it's not subclassable. 0025 - fileno() is left unimplemented so that code which uses it triggers 0026 an exception early. 0027 - Seeking far beyond EOF and then writing will insert real null 0028 bytes that occupy space in the buffer. 0029 - There's a simple test set (see end of this file). 0030 """ 0031 try: 0032 from errno import EINVAL 0033 except ImportError: 0034 EINVAL = 22 0035 0036 __all__ = ["StringIO"] 0037 0038 def _complain_ifclosed(closed): 0039 if closed: 0040 raise ValueError, "I/O operation on closed file" 0041 0042 class StringIO: 0043 """class StringIO([buffer]) 0044 0045 When a StringIO object is created, it can be initialized to an existing 0046 string by passing the string to the constructor. If no string is given, 0047 the StringIO will start empty. 0048 0049 The StringIO object can accept either Unicode or 8-bit strings, but 0050 mixing the two may take some care. If both are used, 8-bit strings that 0051 cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause 0052 a UnicodeError to be raised when getvalue() is called. 0053 """ 0054 def __init__(self, buf = ''): 0055 # Force self.buf to be a string or unicode 0056 if not isinstance(buf, basestring): 0057 buf = str(buf) 0058 self.buf = buf 0059 self.len = len(buf) 0060 self.buflist = [] 0061 self.pos = 0 0062 self.closed = False 0063 self.softspace = 0 0064 0065 def __iter__(self): 0066 return self 0067 0068 def next(self): 0069 """A file object is its own iterator, for example iter(f) returns f 0070 (unless f is closed). When a file is used as an iterator, typically 0071 in a for loop (for example, for line in f: print line), the next() 0072 method is called repeatedly. This method returns the next input line, 0073 or raises StopIteration when EOF is hit. 0074 """ 0075 if self.closed: 0076 raise StopIteration 0077 r = self.readline() 0078 if not r: 0079 raise StopIteration 0080 return r 0081 0082 def close(self): 0083 """Free the memory buffer. 0084 """ 0085 if not self.closed: 0086 self.closed = True 0087 del self.buf, self.pos 0088 0089 def isatty(self): 0090 """Returns False because StringIO objects are not connected to a 0091 tty-like device. 0092 """ 0093 _complain_ifclosed(self.closed) 0094 return False 0095 0096 def seek(self, pos, mode = 0): 0097 """Set the file's current position. 0098 0099 The mode argument is optional and defaults to 0 (absolute file 0100 positioning); other values are 1 (seek relative to the current 0101 position) and 2 (seek relative to the file's end). 0102 0103 There is no return value. 0104 """ 0105 _complain_ifclosed(self.closed) 0106 if self.buflist: 0107 self.buf += ''.join(self.buflist) 0108 self.buflist = [] 0109 if mode == 1: 0110 pos += self.pos 0111 elif mode == 2: 0112 pos += self.len 0113 self.pos = max(0, pos) 0114 0115 def tell(self): 0116 """Return the file's current position.""" 0117 _complain_ifclosed(self.closed) 0118 return self.pos 0119 0120 def read(self, n = -1): 0121 """Read at most size bytes from the file 0122 (less if the read hits EOF before obtaining size bytes). 0123 0124 If the size argument is negative or omitted, read all data until EOF 0125 is reached. The bytes are returned as a string object. An empty 0126 string is returned when EOF is encountered immediately. 0127 """ 0128 _complain_ifclosed(self.closed) 0129 if self.buflist: 0130 self.buf += ''.join(self.buflist) 0131 self.buflist = [] 0132 if n < 0: 0133 newpos = self.len 0134 else: 0135 newpos = min(self.pos+n, self.len) 0136 r = self.buf[self.pos:newpos] 0137 self.pos = newpos 0138 return r 0139 0140 def readline(self, length=None): 0141 """Read one entire line from the file. 0142 0143 A trailing newline character is kept in the string (but may be absent 0144 when a file ends with an incomplete line). If the size argument is 0145 present and non-negative, it is a maximum byte count (including the 0146 trailing newline) and an incomplete line may be returned. 0147 0148 An empty string is returned only when EOF is encountered immediately. 0149 0150 Note: Unlike stdio's fgets(), the returned string contains null 0151 characters ('\0') if they occurred in the input. 0152 """ 0153 _complain_ifclosed(self.closed) 0154 if self.buflist: 0155 self.buf += ''.join(self.buflist) 0156 self.buflist = [] 0157 i = self.buf.find('\n', self.pos) 0158 if i < 0: 0159 newpos = self.len 0160 else: 0161 newpos = i+1 0162 if length is not None: 0163 if self.pos + length < newpos: 0164 newpos = self.pos + length 0165 r = self.buf[self.pos:newpos] 0166 self.pos = newpos 0167 return r 0168 0169 def readlines(self, sizehint = 0): 0170 """Read until EOF using readline() and return a list containing the 0171 lines thus read. 0172 0173 If the optional sizehint argument is present, instead of reading up 0174 to EOF, whole lines totalling approximately sizehint bytes (or more 0175 to accommodate a final whole line). 0176 """ 0177 total = 0 0178 lines = [] 0179 line = self.readline() 0180 while line: 0181 lines.append(line) 0182 total += len(line) 0183 if 0 < sizehint <= total: 0184 break 0185 line = self.readline() 0186 return lines 0187 0188 def truncate(self, size=None): 0189 """Truncate the file's size. 0190 0191 If the optional size argument is present, the file is truncated to 0192 (at most) that size. The size defaults to the current position. 0193 The current file position is not changed unless the position 0194 is beyond the new file size. 0195 0196 If the specified size exceeds the file's current size, the 0197 file remains unchanged. 0198 """ 0199 _complain_ifclosed(self.closed) 0200 if size is None: 0201 size = self.pos 0202 elif size < 0: 0203 raise IOError(EINVAL, "Negative size not allowed") 0204 elif size < self.pos: 0205 self.pos = size 0206 self.buf = self.getvalue()[:size] 0207 0208 def write(self, s): 0209 """Write a string to the file. 0210 0211 There is no return value. 0212 """ 0213 _complain_ifclosed(self.closed) 0214 if not s: return 0215 # Force s to be a string or unicode 0216 if not isinstance(s, basestring): 0217 s = str(s) 0218 spos = self.pos 0219 slen = self.len 0220 if spos == slen: 0221 self.buflist.append(s) 0222 self.len = self.pos = spos + len(s) 0223 return 0224 if spos > slen: 0225 self.buflist.append('\0'*(spos - slen)) 0226 slen = spos 0227 newpos = spos + len(s) 0228 if spos < slen: 0229 if self.buflist: 0230 self.buf += ''.join(self.buflist) 0231 self.buflist = [self.buf[:spos], s, self.buf[newpos:]] 0232 self.buf = '' 0233 if newpos > slen: 0234 slen = newpos 0235 else: 0236 self.buflist.append(s) 0237 slen = newpos 0238 self.len = slen 0239 self.pos = newpos 0240 0241 def writelines(self, iterable): 0242 """Write a sequence of strings to the file. The sequence can be any 0243 iterable object producing strings, typically a list of strings. There 0244 is no return value. 0245 0246 (The name is intended to match readlines(); writelines() does not add 0247 line separators.) 0248 """ 0249 write = self.write 0250 for line in iterable: 0251 write(line) 0252 0253 def flush(self): 0254 """Flush the internal buffer 0255 """ 0256 _complain_ifclosed(self.closed) 0257 0258 def getvalue(self): 0259 """ 0260 Retrieve the entire contents of the "file" at any time before 0261 the StringIO object's close() method is called. 0262 0263 The StringIO object can accept either Unicode or 8-bit strings, 0264 but mixing the two may take some care. If both are used, 8-bit 0265 strings that cannot be interpreted as 7-bit ASCII (that use the 0266 8th bit) will cause a UnicodeError to be raised when getvalue() 0267 is called. 0268 """ 0269 if self.buflist: 0270 self.buf += ''.join(self.buflist) 0271 self.buflist = [] 0272 return self.buf 0273 0274 0275 # A little test suite 0276 0277 def test(): 0278 import sys 0279 if sys.argv[1:]: 0280 file = sys.argv[1] 0281 else: 0282 file = '/etc/passwd' 0283 lines = open(file, 'r').readlines() 0284 text = open(file, 'r').read() 0285 f = StringIO() 0286 for line in lines[:-2]: 0287 f.write(line) 0288 f.writelines(lines[-2:]) 0289 if f.getvalue() != text: 0290 raise RuntimeError, 'write failed' 0291 length = f.tell() 0292 print 'File length =', length 0293 f.seek(len(lines[0])) 0294 f.write(lines[1]) 0295 f.seek(0) 0296 print 'First line =', repr(f.readline()) 0297 print 'Position =', f.tell() 0298 line = f.readline() 0299 print 'Second line =', repr(line) 0300 f.seek(-len(line), 1) 0301 line2 = f.read(len(line)) 0302 if line != line2: 0303 raise RuntimeError, 'bad result after seek back' 0304 f.seek(len(line2), 1) 0305 list = f.readlines() 0306 line = list[-1] 0307 f.seek(f.tell() - len(line)) 0308 line2 = f.read() 0309 if line != line2: 0310 raise RuntimeError, 'bad result after seek back from EOF' 0311 print 'Read', len(list), 'more lines' 0312 print 'File length =', f.tell() 0313 if f.tell() != length: 0314 raise RuntimeError, 'bad length' 0315 f.close() 0316 0317 if __name__ == '__main__': 0318 test() 0319
Generated by PyXR 0.9.4