blob: bdf11cc3799308c81a9f638ac5b85c32ea323d3a [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"""
Marc-André Lemburgf853be92002-01-06 17:15:05 +000031import types
Barry Warsawc7ed0e32000-12-12 23:12:23 +000032try:
Barry Warsawc1401312000-12-12 23:16:51 +000033 from errno import EINVAL
Barry Warsawc7ed0e32000-12-12 23:12:23 +000034except ImportError:
Barry Warsawc1401312000-12-12 23:16:51 +000035 EINVAL = 22
Barry Warsawc7ed0e32000-12-12 23:12:23 +000036
Skip Montanaroe99d5ea2001-01-20 19:54:20 +000037__all__ = ["StringIO"]
38
Guido van Rossum85d89451994-06-23 11:53:27 +000039class StringIO:
Tim Peters8ac14952002-05-23 15:15:30 +000040 """class StringIO([buffer])
41
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000042 When a StringIO object is created, it can be initialized to an existing
43 string by passing the string to the constructor. If no string is given,
Tim Peters8ac14952002-05-23 15:15:30 +000044 the StringIO will start empty.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000045
46 The StringIO object can accept either Unicode or 8-bit strings, but
47 mixing the two may take some care. If both are used, 8-bit strings that
48 cannot be interpreted as 7-bit ASCII (that use the 8th bit) will cause
Tim Peters8ac14952002-05-23 15:15:30 +000049 a UnicodeError to be raised when getvalue() is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000050 """
Barry Warsawc1401312000-12-12 23:16:51 +000051 def __init__(self, buf = ''):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000052 # Force self.buf to be a string or unicode
Michael W. Hudsone1c67d12002-05-13 09:42:16 +000053 if not isinstance(buf, types.StringTypes):
Marc-André Lemburgf853be92002-01-06 17:15:05 +000054 buf = str(buf)
55 self.buf = buf
Fred Drakea63bd1c2000-12-13 20:23:11 +000056 self.len = len(buf)
57 self.buflist = []
58 self.pos = 0
59 self.closed = 0
60 self.softspace = 0
Barry Warsawc1401312000-12-12 23:16:51 +000061
Barry Warsawbdefa0b2001-09-22 04:34:54 +000062 def __iter__(self):
63 return iter(self.readline, '')
64
Barry Warsawc1401312000-12-12 23:16:51 +000065 def close(self):
Tim Peters8ac14952002-05-23 15:15:30 +000066 """Free the memory buffer.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +000067 """
Fred Drakea63bd1c2000-12-13 20:23:11 +000068 if not self.closed:
69 self.closed = 1
70 del self.buf, self.pos
Barry Warsawc1401312000-12-12 23:16:51 +000071
72 def isatty(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000073 if self.closed:
74 raise ValueError, "I/O operation on closed file"
Guido van Rossum8ca162f2002-04-07 06:36:23 +000075 return False
Barry Warsawc1401312000-12-12 23:16:51 +000076
77 def seek(self, pos, mode = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +000078 if self.closed:
79 raise ValueError, "I/O operation on closed file"
80 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +000081 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +000082 self.buflist = []
83 if mode == 1:
84 pos += self.pos
85 elif mode == 2:
86 pos += self.len
87 self.pos = max(0, pos)
Barry Warsawc1401312000-12-12 23:16:51 +000088
89 def tell(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +000090 if self.closed:
91 raise ValueError, "I/O operation on closed file"
92 return self.pos
Barry Warsawc1401312000-12-12 23:16:51 +000093
94 def read(self, n = -1):
Fred Drakea63bd1c2000-12-13 20:23:11 +000095 if self.closed:
96 raise ValueError, "I/O operation on closed file"
97 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +000098 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +000099 self.buflist = []
100 if n < 0:
101 newpos = self.len
102 else:
103 newpos = min(self.pos+n, self.len)
104 r = self.buf[self.pos:newpos]
105 self.pos = newpos
106 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000107
108 def readline(self, length=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000109 if self.closed:
110 raise ValueError, "I/O operation on closed file"
111 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000112 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000113 self.buflist = []
114 i = self.buf.find('\n', self.pos)
115 if i < 0:
116 newpos = self.len
117 else:
118 newpos = i+1
119 if length is not None:
120 if self.pos + length < newpos:
121 newpos = self.pos + length
122 r = self.buf[self.pos:newpos]
123 self.pos = newpos
124 return r
Barry Warsawc1401312000-12-12 23:16:51 +0000125
126 def readlines(self, sizehint = 0):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000127 total = 0
128 lines = []
129 line = self.readline()
130 while line:
131 lines.append(line)
132 total += len(line)
133 if 0 < sizehint <= total:
134 break
135 line = self.readline()
136 return lines
Barry Warsawc1401312000-12-12 23:16:51 +0000137
138 def truncate(self, size=None):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000139 if self.closed:
140 raise ValueError, "I/O operation on closed file"
141 if size is None:
142 size = self.pos
143 elif size < 0:
144 raise IOError(EINVAL, "Negative size not allowed")
145 elif size < self.pos:
146 self.pos = size
147 self.buf = self.getvalue()[:size]
Barry Warsawc1401312000-12-12 23:16:51 +0000148
149 def write(self, s):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000150 if self.closed:
151 raise ValueError, "I/O operation on closed file"
152 if not s: return
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000153 # Force s to be a string or unicode
Michael W. Hudsone1c67d12002-05-13 09:42:16 +0000154 if not isinstance(s, types.StringTypes):
Marc-André Lemburgf853be92002-01-06 17:15:05 +0000155 s = str(s)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000156 if self.pos > self.len:
157 self.buflist.append('\0'*(self.pos - self.len))
158 self.len = self.pos
159 newpos = self.pos + len(s)
160 if self.pos < self.len:
161 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000162 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000163 self.buflist = []
164 self.buflist = [self.buf[:self.pos], s, self.buf[newpos:]]
165 self.buf = ''
166 if newpos > self.len:
167 self.len = newpos
168 else:
169 self.buflist.append(s)
170 self.len = newpos
171 self.pos = newpos
Barry Warsawc1401312000-12-12 23:16:51 +0000172
173 def writelines(self, list):
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000174 self.write(''.join(list))
Barry Warsawc1401312000-12-12 23:16:51 +0000175
176 def flush(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000177 if self.closed:
178 raise ValueError, "I/O operation on closed file"
Barry Warsawc1401312000-12-12 23:16:51 +0000179
180 def getvalue(self):
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000181 """
182 Retrieve the entire contents of the "file" at any time before
183 the StringIO object's close() method is called.
184
185 The StringIO object can accept either Unicode or 8-bit strings,
186 but mixing the two may take some care. If both are used, 8-bit
187 strings that cannot be interpreted as 7-bit ASCII (that use the
188 8th bit) will cause a UnicodeError to be raised when getvalue()
Tim Peters8ac14952002-05-23 15:15:30 +0000189 is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000190 """
Fred Drakea63bd1c2000-12-13 20:23:11 +0000191 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000192 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000193 self.buflist = []
194 return self.buf
Guido van Rossum85d89451994-06-23 11:53:27 +0000195
196
197# A little test suite
198
199def test():
Barry Warsawc1401312000-12-12 23:16:51 +0000200 import sys
201 if sys.argv[1:]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000202 file = sys.argv[1]
Barry Warsawc1401312000-12-12 23:16:51 +0000203 else:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000204 file = '/etc/passwd'
Barry Warsawc1401312000-12-12 23:16:51 +0000205 lines = open(file, 'r').readlines()
206 text = open(file, 'r').read()
207 f = StringIO()
208 for line in lines[:-2]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000209 f.write(line)
Barry Warsawc1401312000-12-12 23:16:51 +0000210 f.writelines(lines[-2:])
211 if f.getvalue() != text:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000212 raise RuntimeError, 'write failed'
Barry Warsawc1401312000-12-12 23:16:51 +0000213 length = f.tell()
214 print 'File length =', length
215 f.seek(len(lines[0]))
216 f.write(lines[1])
217 f.seek(0)
218 print 'First line =', `f.readline()`
Neal Norwitz9fb289d2002-02-11 17:52:18 +0000219 print 'Position =', f.tell()
Barry Warsawc1401312000-12-12 23:16:51 +0000220 line = f.readline()
221 print 'Second line =', `line`
222 f.seek(-len(line), 1)
223 line2 = f.read(len(line))
224 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000225 raise RuntimeError, 'bad result after seek back'
Barry Warsawc1401312000-12-12 23:16:51 +0000226 f.seek(len(line2), 1)
227 list = f.readlines()
228 line = list[-1]
229 f.seek(f.tell() - len(line))
230 line2 = f.read()
231 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000232 raise RuntimeError, 'bad result after seek back from EOF'
Barry Warsawc1401312000-12-12 23:16:51 +0000233 print 'Read', len(list), 'more lines'
234 print 'File length =', f.tell()
235 if f.tell() != length:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000236 raise RuntimeError, 'bad length'
Barry Warsawc1401312000-12-12 23:16:51 +0000237 f.close()
Guido van Rossum85d89451994-06-23 11:53:27 +0000238
239if __name__ == '__main__':
Barry Warsawc1401312000-12-12 23:16:51 +0000240 test()