blob: 7c4b6c7705c71583600b22616ea20174f53f178a [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 Drakea63bd1c2000-12-13 20:23:11 +0000155 if self.pos > self.len:
156 self.buflist.append('\0'*(self.pos - self.len))
157 self.len = self.pos
158 newpos = self.pos + len(s)
159 if self.pos < self.len:
160 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000161 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000162 self.buflist = []
163 self.buflist = [self.buf[:self.pos], s, self.buf[newpos:]]
164 self.buf = ''
165 if newpos > self.len:
166 self.len = newpos
167 else:
168 self.buflist.append(s)
169 self.len = newpos
170 self.pos = newpos
Barry Warsawc1401312000-12-12 23:16:51 +0000171
172 def writelines(self, list):
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000173 self.write(''.join(list))
Barry Warsawc1401312000-12-12 23:16:51 +0000174
175 def flush(self):
Fred Drakea63bd1c2000-12-13 20:23:11 +0000176 if self.closed:
177 raise ValueError, "I/O operation on closed file"
Barry Warsawc1401312000-12-12 23:16:51 +0000178
179 def getvalue(self):
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000180 """
181 Retrieve the entire contents of the "file" at any time before
182 the StringIO object's close() method is called.
183
184 The StringIO object can accept either Unicode or 8-bit strings,
185 but mixing the two may take some care. If both are used, 8-bit
186 strings that cannot be interpreted as 7-bit ASCII (that use the
187 8th bit) will cause a UnicodeError to be raised when getvalue()
Tim Peters8ac14952002-05-23 15:15:30 +0000188 is called.
Raymond Hettingerd1fa3db2002-05-15 02:56:03 +0000189 """
Fred Drakea63bd1c2000-12-13 20:23:11 +0000190 if self.buflist:
Marc-André Lemburg85d6edf2001-02-09 13:37:37 +0000191 self.buf += ''.join(self.buflist)
Fred Drakea63bd1c2000-12-13 20:23:11 +0000192 self.buflist = []
193 return self.buf
Guido van Rossum85d89451994-06-23 11:53:27 +0000194
195
196# A little test suite
197
198def test():
Barry Warsawc1401312000-12-12 23:16:51 +0000199 import sys
200 if sys.argv[1:]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000201 file = sys.argv[1]
Barry Warsawc1401312000-12-12 23:16:51 +0000202 else:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000203 file = '/etc/passwd'
Barry Warsawc1401312000-12-12 23:16:51 +0000204 lines = open(file, 'r').readlines()
205 text = open(file, 'r').read()
206 f = StringIO()
207 for line in lines[:-2]:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000208 f.write(line)
Barry Warsawc1401312000-12-12 23:16:51 +0000209 f.writelines(lines[-2:])
210 if f.getvalue() != text:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000211 raise RuntimeError, 'write failed'
Barry Warsawc1401312000-12-12 23:16:51 +0000212 length = f.tell()
213 print 'File length =', length
214 f.seek(len(lines[0]))
215 f.write(lines[1])
216 f.seek(0)
217 print 'First line =', `f.readline()`
Neal Norwitz9fb289d2002-02-11 17:52:18 +0000218 print 'Position =', f.tell()
Barry Warsawc1401312000-12-12 23:16:51 +0000219 line = f.readline()
220 print 'Second line =', `line`
221 f.seek(-len(line), 1)
222 line2 = f.read(len(line))
223 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000224 raise RuntimeError, 'bad result after seek back'
Barry Warsawc1401312000-12-12 23:16:51 +0000225 f.seek(len(line2), 1)
226 list = f.readlines()
227 line = list[-1]
228 f.seek(f.tell() - len(line))
229 line2 = f.read()
230 if line != line2:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000231 raise RuntimeError, 'bad result after seek back from EOF'
Barry Warsawc1401312000-12-12 23:16:51 +0000232 print 'Read', len(list), 'more lines'
233 print 'File length =', f.tell()
234 if f.tell() != length:
Fred Drakea63bd1c2000-12-13 20:23:11 +0000235 raise RuntimeError, 'bad length'
Barry Warsawc1401312000-12-12 23:16:51 +0000236 f.close()
Guido van Rossum85d89451994-06-23 11:53:27 +0000237
238if __name__ == '__main__':
Barry Warsawc1401312000-12-12 23:16:51 +0000239 test()