PyXR

c:\python24\lib \ StringIO.py



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
SourceForge.net Logo