'Similar to file.read(), but returns the contents of the underlying
file as a numpy array (or mmap\'d array if memmap=True) rather than a
string.
Usually it\'s best not to use the `size` argument with this method, but
it\'s provided for compatibility.'

def readarray(self, size=None, offset=0, dtype=np.uint8, shape=None):

    if (not hasattr(self._file, 'read')):
        raise EOFError
    if (not isinstance(dtype, np.dtype)):
        dtype = np.dtype(dtype)
    if (size and ((size % dtype.itemsize) != 0)):
        raise ValueError('size    {}    not    a    multiple    of    {}'.format(size, dtype))
    if isinstance(shape, int):
        shape = (shape,)
    if (not (size or shape)):
        warnings.warn('No    size    or    shape    given    to    readarray();    assuming    a    shape    of    (1,)', AstropyUserWarning)
        shape = (1,)
    if (size and (not shape)):
        shape = ((size // dtype.itemsize),)
    if (size and shape):
        actualsize = (np.prod(shape) * dtype.itemsize)
        if (actualsize < size):
            raise ValueError('size    {}    is    too    few    bytes    for    a    {}    array    of    {}'.format(size, shape, dtype))
        if (actualsize < size):
            raise ValueError('size    {}    is    too    many    bytes    for    a    {}    array    of    {}'.format(size, shape, dtype))
    filepos = self._file.tell()
    try:
        if self.memmap:
            if (self._mmap is None):
                memmap = Memmap(self._file, mode=MEMMAP_MODES[self.mode], dtype=np.uint8)
                self._mmap = memmap.base
                memmap._mmap = None
                del memmap
            return np.ndarray(shape=shape, dtype=dtype, offset=offset, buffer=self._mmap)
        else:
            count = reduce(operator.mul, shape)
            self._file.seek(offset)
            data = _array_from_file(self._file, dtype, count, '')
            data.shape = shape
            return data
    finally:
        self._file.seek(filepos)
