blob: 79ab7e16b3291c35da4f4cecffa9c6b03fa542da [file] [log] [blame]
Guido van Rossum4acc25b2000-02-02 15:10:15 +00001"""File-like objects that read from or write to a string buffer.
2
3This implements (nearly) all stdio methods.
4
5f = StringIO() # ready for writing
6f = StringIO(buf) # ready for reading
7f.close() # explicitly release resources held
8flag = f.isatty() # always false
9pos = f.tell() # get current position
10f.seek(pos) # set current position
11f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
12buf = f.read() # read until EOF
13buf = f.read(n) # read up to n bytes
14buf = f.readline() # read until end of line ('\n') or EOF
15list = f.readlines()# list of f.readline() results until EOF
Fred Drakee0a7f4f2000-09-28 04:21:06 +000016f.truncate([size]) # truncate file at to at most size (default: current pos)
Guido van Rossum4acc25b2000-02-02 15:10:15 +000017f.write(buf) # write at current position
18f.writelines(list) # for line in list: f.write(line)
19f.getvalue() # return whole file's contents as a string
20
21Notes:
22- Using a real file is often faster (but less convenient).
Guido van Rossum98d9fd32000-02-28 15:12:25 +000023- There's also a much faster implementation in C, called cStringIO, but
24 it's not subclassable.
Guido van Rossum4acc25b2000-02-02 15:10:15 +000025- fileno() is left unimplemented so that code which uses it triggers
26 an exception early.
27- Seeking far beyond EOF and then writing will insert real null
28 bytes that occupy space in the buffer.
29- There's a simple test set (see end of this file).
30"""
Barry Warsawc7ed0e32000-12-12 23:12:23 +000031try:
Barry Warsawc1401312000-12-12 23:16:51 +000032 from errno import EINVAL
Barry Warsawc7ed0e32000-12-12 23:12:23 +000033except ImportError:
Barry Warsawc1401312000-12-12 23:16:51 +000034 EINVAL = 22
Barry Warsawc7ed0e32000-12-12 23:12:23 +000035
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000036__all__ = ["StringIO"]
37
Guido van Rossum85d89451994-06-23 11:53:27 +000038class StringIO:
Tim Peters8ac14952002-05-23 15:15:30 +000039 """class StringIO([buffer])
40
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000041 When a StringIO object is created, it can be initialized to an existing
42 string by passing the string to the constructor. If no string is given,
Tim Peters8ac14952002-05-23 15:15:30 +000043 the StringIO will start empty.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000044
45 The StringIO object can accept either Unicode or 8-bit strings, but
46 mixing the two may take some care. If both are used, 8-bit strings that
47 cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause
Tim Peters8ac14952002-05-23 15:15:30 +000048 a UnicodeError to be raised when getvalue() is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000049 """
Barry Warsawc1401312000-12-12 23:16:51 +000050 def __init__(self, buf = ''):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000051 # Force self.buf to be a string or unicode
Walter Dörwald65230a22002-06-03 15:58:32 +000052 if not isinstance(buf, basestring):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000053 buf = str(buf)
54 self.buf = buf
Fred Drakea63bd1c2000-12-13 20:23:11 +000055 self.len = len(buf)
56 self.buflist = []
57 self.pos = 0
58 self.closed = 0
59 self.softspace = 0
Barry Warsawc1401312000-12-12 23:16:51 +000060
Barry Warsawbdefa0b2001-09-22 04:34:54 +000061 def __iter__(self):
62 return iter(self.readline, '')
63
Barry Warsawc1401312000-12-12 23:16:51 +000064 def close(self):
Tim Peters8ac14952002-05-23 15:15:30 +000065 """Free the memory buffer.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000066 """
Fred Drakea63bd1c2000-12-13 20:23:11 +000067 if not self.closed:
68 self.closed = 1
69 del self.buf, self.pos
Barry Warsawc1401312000-12-12 23:16:51 +000070
71 def isatty(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000072 if self.closed:
73 raise ValueError, "I/O operation on closed file"
Guido van Rossum8ca162f2002-04-07 06:36:23 +000074 return False
Barry Warsawc1401312000-12-12 23:16:51 +000075
76 def seek(self, pos, mode = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +000077 if self.closed:
78 raise ValueError, "I/O operation on closed file"
79 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +000080 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +000081 self.buflist = []
82 if mode == 1:
83 pos += self.pos
84 elif mode == 2:
85 pos += self.len
86 self.pos = max(0, pos)
Barry Warsawc1401312000-12-12 23:16:51 +000087
88 def tell(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000089 if self.closed:
90 raise ValueError, "I/O operation on closed file"
91 return self.pos
Barry Warsawc1401312000-12-12 23:16:51 +000092
93 def read(self, n = -1):
Fred Drakea63bd1c2000-12-13 20:23:11 +000094 if self.closed:
95 raise ValueError, "I/O operation on closed file"
96 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +000097 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +000098 self.buflist = []
99 if n < 0:
100 newpos = self.len
101 else:
102 newpos = min(self.pos+n, self.len)
103 r = self.buf[self.pos:newpos]
104 self.pos = newpos
105 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000106
107 def readline(self, length=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000108 if self.closed:
109 raise ValueError, "I/O operation on closed file"
110 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000111 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000112 self.buflist = []
113 i = self.buf.find('\n', self.pos)
114 if i < 0:
115 newpos = self.len
116 else:
117 newpos = i+1
118 if length is not None:
119 if self.pos + length < newpos:
120 newpos = self.pos + length
121 r = self.buf[self.pos:newpos]
122 self.pos = newpos
123 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000124
125 def readlines(self, sizehint = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000126 total = 0
127 lines = []
128 line = self.readline()
129 while line:
130 lines.append(line)
131 total += len(line)
132 if 0 < sizehint <= total:
133 break
134 line = self.readline()
135 return lines
Barry Warsawc1401312000-12-12 23:16:51 +0000136
137 def truncate(self, size=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000138 if self.closed:
139 raise ValueError, "I/O operation on closed file"
140 if size is None:
141 size = self.pos
142 elif size < 0:
143 raise IOError(EINVAL, "Negative size not allowed")
144 elif size < self.pos:
145 self.pos = size
146 self.buf = self.getvalue()[:size]
Barry Warsawc1401312000-12-12 23:16:51 +0000147
148 def write(self, s):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000149 if self.closed:
150 raise ValueError, "I/O operation on closed file"
151 if not s: return
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000152 # Force s to be a string or unicode
Walter Dörwald65230a22002-06-03 15:58:32 +0000153 if not isinstance(s, basestring):
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000154 s = str(s)
Fred Draked679e092002-09-17 18:10:34 +0000155 if self.pos == self.len:
156 self.buflist.append(s)
157 self.len = self.pos = self.pos + len(s)
158 return
Fred Drakea63bd1c2000-12-13 20:23:11 +0000159 if self.pos > self.len:
160 self.buflist.append('\0'*(self.pos - self.len))
161 self.len = self.pos
162 newpos = self.pos + len(s)
163 if self.pos < self.len:
164 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000165 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000166 self.buflist = []
167 self.buflist = [self.buf[:self.pos], s, self.buf[newpos:]]
168 self.buf = ''
169 if newpos > self.len:
170 self.len = newpos
171 else:
172 self.buflist.append(s)
173 self.len = newpos
174 self.pos = newpos
Barry Warsawc1401312000-12-12 23:16:51 +0000175
176 def writelines(self, list):
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000177 self.write(''.join(list))
Barry Warsawc1401312000-12-12 23:16:51 +0000178
179 def flush(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000180 if self.closed:
181 raise ValueError, "I/O operation on closed file"
Barry Warsawc1401312000-12-12 23:16:51 +0000182
183 def getvalue(self):
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000184 """
185 Retrieve the entire contents of the "file" at any time before
186 the StringIO object's close() method is called.
187
188 The StringIO object can accept either Unicode or 8-bit strings,
189 but mixing the two may take some care. If both are used, 8-bit
190 strings that cannot be interpreted as 7-bit ASCII (that use the
191 8th bit) will cause a UnicodeError to be raised when getvalue()
Tim Peters8ac14952002-05-23 15:15:30 +0000192 is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000193 """
Fred Drakea63bd1c2000-12-13 20:23:11 +0000194 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000195 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000196 self.buflist = []
197 return self.buf
Guido van Rossum85d89451994-06-23 11:53:27 +0000198
199
200# A little test suite
201
202def test():
Barry Warsawc1401312000-12-12 23:16:51 +0000203 import sys
204 if sys.argv[1:]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000205 file = sys.argv[1]
Barry Warsawc1401312000-12-12 23:16:51 +0000206 else:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000207 file = '/etc/passwd'
Barry Warsawc1401312000-12-12 23:16:51 +0000208 lines = open(file, 'r').readlines()
209 text = open(file, 'r').read()
210 f = StringIO()
211 for line in lines[:-2]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000212 f.write(line)
Barry Warsawc1401312000-12-12 23:16:51 +0000213 f.writelines(lines[-2:])
214 if f.getvalue() != text:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000215 raise RuntimeError, 'write failed'
Barry Warsawc1401312000-12-12 23:16:51 +0000216 length = f.tell()
217 print 'File length =', length
218 f.seek(len(lines[0]))
219 f.write(lines[1])
220 f.seek(0)
221 print 'First line =', `f.readline()`
Neal Norwitz9fb289d2002-02-11 17:52:18 +0000222 print 'Position =', f.tell()
Barry Warsawc1401312000-12-12 23:16:51 +0000223 line = f.readline()
224 print 'Second line =', `line`
225 f.seek(-len(line), 1)
226 line2 = f.read(len(line))
227 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000228 raise RuntimeError, 'bad result after seek back'
Barry Warsawc1401312000-12-12 23:16:51 +0000229 f.seek(len(line2), 1)
230 list = f.readlines()
231 line = list[-1]
232 f.seek(f.tell() - len(line))
233 line2 = f.read()
234 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000235 raise RuntimeError, 'bad result after seek back from EOF'
Barry Warsawc1401312000-12-12 23:16:51 +0000236 print 'Read', len(list), 'more lines'
237 print 'File length =', f.tell()
238 if f.tell() != length:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000239 raise RuntimeError, 'bad length'
Barry Warsawc1401312000-12-12 23:16:51 +0000240 f.close()
Guido van Rossum85d89451994-06-23 11:53:27 +0000241
242if __name__ == '__main__':
Barry Warsawc1401312000-12-12 23:16:51 +0000243 test()