ContainerIO.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #
  2. # The Python Imaging Library.
  3. # $Id$
  4. #
  5. # a class to read from a container file
  6. #
  7. # History:
  8. # 1995-06-18 fl Created
  9. # 1995-09-07 fl Added readline(), readlines()
  10. #
  11. # Copyright (c) 1997-2001 by Secret Labs AB
  12. # Copyright (c) 1995 by Fredrik Lundh
  13. #
  14. # See the README file for information on usage and redistribution.
  15. #
  16. import io
  17. class ContainerIO:
  18. """
  19. A file object that provides read access to a part of an existing
  20. file (for example a TAR file).
  21. """
  22. def __init__(self, file, offset, length):
  23. """
  24. Create file object.
  25. :param file: Existing file.
  26. :param offset: Start of region, in bytes.
  27. :param length: Size of region, in bytes.
  28. """
  29. self.fh = file
  30. self.pos = 0
  31. self.offset = offset
  32. self.length = length
  33. self.fh.seek(offset)
  34. ##
  35. # Always false.
  36. def isatty(self):
  37. return False
  38. def seek(self, offset, mode=io.SEEK_SET):
  39. """
  40. Move file pointer.
  41. :param offset: Offset in bytes.
  42. :param mode: Starting position. Use 0 for beginning of region, 1
  43. for current offset, and 2 for end of region. You cannot move
  44. the pointer outside the defined region.
  45. """
  46. if mode == 1:
  47. self.pos = self.pos + offset
  48. elif mode == 2:
  49. self.pos = self.length + offset
  50. else:
  51. self.pos = offset
  52. # clamp
  53. self.pos = max(0, min(self.pos, self.length))
  54. self.fh.seek(self.offset + self.pos)
  55. def tell(self):
  56. """
  57. Get current file pointer.
  58. :returns: Offset from start of region, in bytes.
  59. """
  60. return self.pos
  61. def read(self, n=0):
  62. """
  63. Read data.
  64. :param n: Number of bytes to read. If omitted or zero,
  65. read until end of region.
  66. :returns: An 8-bit string.
  67. """
  68. if n:
  69. n = min(n, self.length - self.pos)
  70. else:
  71. n = self.length - self.pos
  72. if not n: # EOF
  73. return b"" if "b" in self.fh.mode else ""
  74. self.pos = self.pos + n
  75. return self.fh.read(n)
  76. def readline(self):
  77. """
  78. Read a line of text.
  79. :returns: An 8-bit string.
  80. """
  81. s = b"" if "b" in self.fh.mode else ""
  82. newline_character = b"\n" if "b" in self.fh.mode else "\n"
  83. while True:
  84. c = self.read(1)
  85. if not c:
  86. break
  87. s = s + c
  88. if c == newline_character:
  89. break
  90. return s
  91. def readlines(self):
  92. """
  93. Read multiple lines of text.
  94. :returns: A list of 8-bit strings.
  95. """
  96. lines = []
  97. while True:
  98. s = self.readline()
  99. if not s:
  100. break
  101. lines.append(s)
  102. return lines