1 """File-like objects that read from or write to a string buffer.
3 This implements (nearly) all stdio methods.
5 f = StringIO() # ready for writing
6 f = StringIO(buf) # ready for reading
7 f.close() # explicitly release resources held
8 flag = f.isatty() # always false
9 pos = f.tell() # get current position
10 f.seek(pos) # set current position
11 f.seek(pos, mode) # mode 0: absolute; 1: relative; 2: relative to EOF
12 buf = f.read() # read until EOF
13 buf = f.read(n) # read up to n bytes
14 buf = f.readline() # read until end of line ('\n') or EOF
15 list = f.readlines()# list of f.readline() results until EOF
16 f.truncate([size]) # truncate file at to at most size (default: current pos)
17 f.write(buf) # write at current position
18 f.writelines(list) # for line in list: f.write(line)
19 f.getvalue() # return whole file's contents as a string
22 - Using a real file is often faster (but less convenient).
23 - There's also a much faster implementation in C, called cStringIO, but
24 it's not subclassable.
25 - fileno() is left unimplemented so that code which uses it triggers
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).
32 from errno
import EINVAL
36 __all__
= ["StringIO"]
39 """class StringIO([buffer])
41 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,
43 the StringIO will start empty.
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
48 a UnicodeError to be raised when getvalue() is called.
50 def __init__(self
, buf
= ''):
51 # Force self.buf to be a string or unicode
52 if not isinstance(buf
, basestring
):
62 return iter(self
.readline
, '')
65 """Free the memory buffer.
69 del self
.buf
, self
.pos
73 raise ValueError, "I/O operation on closed file"
76 def seek(self
, pos
, mode
= 0):
78 raise ValueError, "I/O operation on closed file"
80 self
.buf
+= ''.join(self
.buflist
)
86 self
.pos
= max(0, pos
)
90 raise ValueError, "I/O operation on closed file"
93 def read(self
, n
= -1):
95 raise ValueError, "I/O operation on closed file"
97 self
.buf
+= ''.join(self
.buflist
)
102 newpos
= min(self
.pos
+n
, self
.len)
103 r
= self
.buf
[self
.pos
:newpos
]
107 def readline(self
, length
=None):
109 raise ValueError, "I/O operation on closed file"
111 self
.buf
+= ''.join(self
.buflist
)
113 i
= self
.buf
.find('\n', self
.pos
)
118 if length
is not None:
119 if self
.pos
+ length
< newpos
:
120 newpos
= self
.pos
+ length
121 r
= self
.buf
[self
.pos
:newpos
]
125 def readlines(self
, sizehint
= 0):
128 line
= self
.readline()
132 if 0 < sizehint
<= total
:
134 line
= self
.readline()
137 def truncate(self
, size
=None):
139 raise ValueError, "I/O operation on closed file"
143 raise IOError(EINVAL
, "Negative size not allowed")
144 elif size
< self
.pos
:
146 self
.buf
= self
.getvalue()[:size
]
150 raise ValueError, "I/O operation on closed file"
152 # Force s to be a string or unicode
153 if not isinstance(s
, basestring
):
155 if self
.pos
> self
.len:
156 self
.buflist
.append('\0'*(self
.pos
- self
.len))
158 newpos
= self
.pos
+ len(s
)
159 if self
.pos
< self
.len:
161 self
.buf
+= ''.join(self
.buflist
)
163 self
.buflist
= [self
.buf
[:self
.pos
], s
, self
.buf
[newpos
:]]
165 if newpos
> self
.len:
168 self
.buflist
.append(s
)
172 def writelines(self
, list):
173 self
.write(''.join(list))
177 raise ValueError, "I/O operation on closed file"
181 Retrieve the entire contents of the "file" at any time before
182 the StringIO object's close() method is called.
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()
191 self
.buf
+= ''.join(self
.buflist
)
196 # A little test suite
204 lines
= open(file, 'r').readlines()
205 text
= open(file, 'r').read()
207 for line
in lines
[:-2]:
209 f
.writelines(lines
[-2:])
210 if f
.getvalue() != text
:
211 raise RuntimeError, 'write failed'
213 print 'File length =', length
214 f
.seek(len(lines
[0]))
217 print 'First line =', `f
.readline()`
218 print 'Position =', f
.tell()
220 print 'Second line =', `line`
221 f
.seek(-len(line
), 1)
222 line2
= f
.read(len(line
))
224 raise RuntimeError, 'bad result after seek back'
225 f
.seek(len(line2
), 1)
228 f
.seek(f
.tell() - len(line
))
231 raise RuntimeError, 'bad result after seek back from EOF'
232 print 'Read', len(list), 'more lines'
233 print 'File length =', f
.tell()
234 if f
.tell() != length
:
235 raise RuntimeError, 'bad length'
238 if __name__
== '__main__':