feat: Android-pyApi v1.0 - 全面翻译 Android SDK API 为 Python

52 个模块覆盖 Android + Java + org.json 标准库
This commit is contained in:
shuiyu1123 committed 2026-06-24 11:16:16 +00:00
commit bfe27fdc08
104 files changed
+58750

No files matched your search

+697
View File
@@ -0,0 +1,697 @@
"""
Java zip standard library APIs implemented in Python.
java.util.zip package - ZipFile, ZipEntry, GZIP, CRC, Deflater, Inflater.
"""
from .._core import Stub
from .io import IOException, Closeable, Flushable
import zipfile as _zipfile
import gzip as _gzip
import zlib as _zlib
import io as _pyio
import os as _os
from datetime import datetime as _datetime
__all__ = [
"ZipFile", "ZipEntry", "ZipOutputStream", "ZipInputStream",
"GZIPInputStream", "GZIPOutputStream",
"CRC32", "CheckedInputStream", "CheckedOutputStream",
"Adler32",
"DataFormatException", "ZipException",
"Deflater", "Inflater",
"DeflaterOutputStream", "InflaterInputStream",
]
# ============================================================
# Exception classes
# ============================================================
class ZipException(IOException):
pass
class DataFormatException(Exception):
pass
# ============================================================
# CRC32
# ============================================================
class CRC32(Stub):
def __init__(self):
super().__init__()
self._value = 0
def getValue(self):
return self._value
def reset(self):
self._value = 0
def update(self, b, off=None, length=None):
if isinstance(b, int):
self._value = _zlib.crc32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._value = _zlib.crc32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
else:
self._value = _zlib.crc32(bytes(b), self._value) & 0xFFFFFFFF
# ============================================================
# Adler32
# ============================================================
class Adler32(Stub):
def __init__(self):
super().__init__()
self._value = 1
def getValue(self):
return self._value
def reset(self):
self._value = 1
def update(self, b, off=None, length=None):
if isinstance(b, int):
self._value = _zlib.adler32(bytes([b & 0xFF]), self._value) & 0xFFFFFFFF
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._value = _zlib.adler32(bytes(b[off:off+length]), self._value) & 0xFFFFFFFF
else:
self._value = _zlib.adler32(bytes(b), self._value) & 0xFFFFFFFF
# ============================================================
# CheckedInputStream / CheckedOutputStream
# ============================================================
class CheckedInputStream(Closeable):
def __init__(self, inp, cksum):
super().__init__()
self._in = inp
self._cksum = cksum
def read(self, b=None, off=None, length=None):
if b is None:
result = self._in.read()
if result >= 0:
self._cksum.update(result)
return result
if off is None:
off = 0
if length is None:
length = len(b)
result = self._in.read(b, off, length)
if result > 0:
self._cksum.update(b[off:off+result])
return result
def getChecksum(self):
return self._cksum
def close(self):
self._in.close()
def skip(self, n):
return self._in.skip(n)
class CheckedOutputStream(Closeable, Flushable):
def __init__(self, out, cksum):
super().__init__()
self._out = out
self._cksum = cksum
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._out.write(b)
self._cksum.update(b)
else:
if off is not None and length is not None:
data = bytes(b[off:off+length])
else:
data = bytes(b)
self._out.write(data)
self._cksum.update(data)
def getChecksum(self):
return self._cksum
def flush(self):
self._out.flush()
def close(self):
self._out.close()
# ============================================================
# ZipEntry
# ============================================================
class ZipEntry(Stub):
STORED = 0
DEFLATED = 8
def __init__(self, name):
super().__init__()
self._name = name
self._method = ZipEntry.DEFLATED
self._size = 0
self._compressed_size = 0
self._crc = 0
self._comment = ""
self._time = 0
self._extra = b""
self._is_directory = name.endswith("/")
def getName(self):
return self._name
def getMethod(self):
return self._method
def setMethod(self, method):
self._method = method
def getSize(self):
return self._size
def setSize(self, size):
self._size = size
def getCompressedSize(self):
return self._compressed_size
def setCompressedSize(self, size):
self._compressed_size = size
def getCrc(self):
return self._crc
def setCrc(self, crc):
self._crc = crc
def getComment(self):
return self._comment
def setComment(self, comment):
self._comment = comment
def getTime(self):
return self._time
def setTime(self, time):
self._time = time
def getExtra(self):
return self._extra
def setExtra(self, extra):
self._extra = extra
def isDirectory(self):
return self._is_directory
def toString(self):
return self._name
def __str__(self):
return self._name
# ============================================================
# ZipFile
# ============================================================
class ZipFile(Closeable):
OPEN_READ = 1
OPEN_DELETE = 2
def __init__(self, file, mode="r"):
super().__init__()
if isinstance(file, str):
path = file
else:
path = file.getPath()
self._path = path
self._mode = mode
try:
self._zfile = _zipfile.ZipFile(path, mode)
except Exception as e:
raise ZipException(str(e))
def entries(self):
return iter(self._zfile.infolist())
def getEntry(self, name):
try:
info = self._zfile.getinfo(name)
entry = ZipEntry(info.filename)
entry.setMethod(info.compress_type)
entry.setSize(info.file_size)
entry.setCompressedSize(info.compress_size)
entry.setCrc(info.CRC)
entry.setTime(int(_datetime(*info.date_time).timestamp() * 1000) if info.date_time else 0)
return entry
except KeyError:
return None
def getInputStream(self, entry):
try:
data = self._zfile.read(entry.getName() if isinstance(entry, ZipEntry) else entry)
from ..io import ByteArrayInputStream
return ByteArrayInputStream(data)
except Exception as e:
raise ZipException(str(e))
def close(self):
self._zfile.close()
def size(self):
return len(self._zfile.namelist())
def getName(self):
return self._path
def getComment(self):
return ""
# ============================================================
# ZipOutputStream
# ============================================================
class ZipOutputStream(Closeable, Flushable):
STORED = 0
DEFLATED = 8
def __init__(self, out):
super().__init__()
self._out = out
self._zfile = _zipfile.ZipFile(out, "w", _zipfile.ZIP_DEFLATED)
self._method = ZipOutputStream.DEFLATED
self._level = -1
self._comment = ""
def putNextEntry(self, entry):
zi = _zipfile.ZipInfo(entry.getName() if isinstance(entry, ZipEntry) else str(entry))
if hasattr(entry, 'getTime') and entry.getTime():
dt = _datetime.fromtimestamp(entry.getTime() / 1000.0)
zi.date_time = dt.timetuple()[:6]
self._zfile.writestr(zi, b"")
def closeEntry(self):
pass
def write(self, b, off=None, length=None):
if off is not None and length is not None:
self._zfile._zout.write(bytes(b[off:off+length]))
else:
self._zfile._zout.write(bytes(b) if not isinstance(b, (bytes, bytearray)) else b)
def finish(self):
self._zfile.close()
def close(self):
self._zfile.close()
def setMethod(self, method):
self._method = method
def setLevel(self, level):
self._level = level
def setComment(self, comment):
self._comment = comment
def flush(self):
self._zfile._zout.flush() if hasattr(self._zfile._zout, 'flush') else None
# ============================================================
# ZipInputStream
# ============================================================
class ZipInputStream(Closeable):
def __init__(self, inp):
super().__init__()
self._inp = inp
self._zfile = _zipfile.ZipFile(inp)
self._entries = iter(self._zfile.infolist())
self._current_entry = None
self._current_data = b""
self._current_pos = 0
def getNextEntry(self):
try:
info = next(self._entries)
entry = ZipEntry(info.filename)
entry.setMethod(info.compress_type)
entry.setSize(info.file_size)
entry.setCompressedSize(info.compress_size)
entry.setCrc(info.CRC)
self._current_entry = info
self._current_data = self._zfile.read(info)
self._current_pos = 0
return entry
except StopIteration:
self._current_entry = None
self._current_data = b""
return None
def read(self, b=None, off=None, length=None):
if self._current_entry is None:
return -1
avail = len(self._current_data) - self._current_pos
if avail <= 0:
return -1
if b is None:
val = self._current_data[self._current_pos]
self._current_pos += 1
return val
if off is None:
off = 0
if length is None:
length = len(b)
n = min(length, avail)
if isinstance(b, bytearray):
b[off:off+n] = self._current_data[self._current_pos:self._current_pos+n]
self._current_pos += n
return n
def closeEntry(self):
self._current_entry = None
self._current_data = b""
def available(self):
if self._current_entry is None:
return 0
return len(self._current_data) - self._current_pos
def close(self):
self._zfile.close()
# ============================================================
# GZIPInputStream
# ============================================================
class GZIPInputStream(Closeable):
def __init__(self, inp, size=512):
super().__init__()
self._inp = inp
self._gzip_file = _gzip.GzipFile(fileobj=_pyio.BufferedReader(inp) if hasattr(inp, 'read') else inp)
def read(self, b=None, off=None, length=None):
if b is None:
data = self._gzip_file.read(1)
return data[0] if data else -1
if off is None:
off = 0
if length is None:
length = len(b)
data = self._gzip_file.read(length)
if not data:
return -1
n = len(data)
if isinstance(b, bytearray):
b[off:off+n] = data
else:
ba = bytearray(b)
ba[off:off+n] = data
b[:] = bytes(ba)
return n
def close(self):
self._gzip_file.close()
# ============================================================
# GZIPOutputStream
# ============================================================
class GZIPOutputStream(Closeable, Flushable):
def __init__(self, out, size=512):
super().__init__()
self._out = out
self._gzip_file = _gzip.GzipFile(fileobj=out, mode="wb")
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._gzip_file.write(bytes([b & 0xFF]))
elif isinstance(b, (bytes, bytearray)):
if off is not None and length is not None:
self._gzip_file.write(bytes(b[off:off+length]))
else:
self._gzip_file.write(bytes(b))
def finish(self):
self._gzip_file.close()
def close(self):
self._gzip_file.close()
def flush(self):
self._gzip_file.flush()
# ============================================================
# Deflater
# ============================================================
class Deflater(Stub):
BEST_COMPRESSION = 9
BEST_SPEED = 1
DEFAULT_COMPRESSION = -1
DEFAULT_STRATEGY = 0
FILTERED = 1
HUFFMAN_ONLY = 2
NO_COMPRESSION = 0
NO_FLUSH = 0
SYNC_FLUSH = 2
FULL_FLUSH = 3
def __init__(self, level=-1, nowrap=False):
super().__init__()
self._level = level
self._nowrap = nowrap
self._compress = _zlib.compressobj(level=level if level >= 0 else 6,
method=_zlib.DEFLATED,
wbits=-_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS)
self._input_buffer = b""
self._finished = False
def setInput(self, data, off=0, length=-1):
if length < 0:
length = len(data) - off
self._input_buffer = bytes(data[off:off+length])
def needsInput(self):
return len(self._input_buffer) == 0
def setDictionary(self, dictionary):
pass
def getTotalIn(self):
return len(self._input_buffer)
def getTotalOut(self):
return 0
def deflate(self, output, off=0, length=-1):
if length < 0:
length = len(output) - off
data = self._compress.compress(self._input_buffer)
self._input_buffer = b""
n = min(len(data), length)
if isinstance(output, bytearray):
output[off:off+n] = data[:n]
else:
ba = bytearray(output)
ba[off:off+n] = data[:n]
output[:] = bytes(ba)
return n
def finish(self):
self._finished = True
def finished(self):
return self._finished
def end(self):
pass
def getAdler(self):
return 1
def reset(self):
self._compress = _zlib.compressobj(level=self._level if self._level >= 0 else 6,
method=_zlib.DEFLATED,
wbits=-_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS)
self._input_buffer = b""
self._finished = False
# ============================================================
# Inflater
# ============================================================
class Inflater(Stub):
def __init__(self, nowrap=False):
super().__init__()
self._nowrap = nowrap
wbits = -_zlib.MAX_WBITS if nowrap else _zlib.MAX_WBITS
self._decompress = _zlib.decompressobj(wbits)
self._input_buffer = b""
self._finished = False
def setInput(self, data, off=0, length=-1):
if length < 0:
length = len(data) - off
self._input_buffer = bytes(data[off:off+length])
def needsInput(self):
return len(self._input_buffer) == 0
def setDictionary(self, dictionary):
pass
def getTotalIn(self):
return len(self._input_buffer)
def getTotalOut(self):
return 0
def inflate(self, output, off=0, length=-1):
if length < 0:
length = len(output) - off
try:
data = self._decompress.decompress(self._input_buffer)
self._input_buffer = b""
n = min(len(data), length)
if isinstance(output, bytearray):
output[off:off+n] = data[:n]
else:
ba = bytearray(output)
ba[off:off+n] = data[:n]
output[:] = bytes(ba)
return n
except _zlib.error as e:
raise DataFormatException(str(e))
def finished(self):
return self._finished
def end(self):
pass
def getAdler(self):
return 1
def needsDictionary(self):
return False
def reset(self):
wbits = -_zlib.MAX_WBITS if self._nowrap else _zlib.MAX_WBITS
self._decompress = _zlib.decompressobj(wbits)
self._input_buffer = b""
self._finished = False
# ============================================================
# DeflaterOutputStream
# ============================================================
class DeflaterOutputStream(Closeable, Flushable):
def __init__(self, out, deflater=None, size=512):
super().__init__()
self._out = out
self._deflater = deflater or Deflater()
self._buffer = bytearray(size)
def write(self, b, off=None, length=None):
if isinstance(b, int):
self._out.write(bytes([b & 0xFF]))
else:
if off is not None and length is not None:
self._out.write(bytes(b[off:off+length]))
else:
self._deflater.setInput(bytes(b) if isinstance(b, (bytes, bytearray)) else bytes(b))
while not self._deflater.needsInput():
n = self._deflater.deflate(self._buffer)
if n > 0:
self._out.write(bytes(self._buffer[:n]))
def finish(self):
self._deflater.finish()
while not self._deflater.finished():
n = self._deflater.deflate(self._buffer)
if n > 0:
self._out.write(bytes(self._buffer[:n]))
def close(self):
self.finish()
self._deflater.end()
self._out.close()
def flush(self):
self._out.flush()
# ============================================================
# InflaterInputStream
# ============================================================
class InflaterInputStream(Closeable):
def __init__(self, inp, inflater=None, size=512):
super().__init__()
self._in = inp
self._inflater = inflater or Inflater()
self._buffer = bytearray(size)
def read(self, b=None, off=None, length=None):
if b is None:
buf = bytearray(1)
n = self._read_from_inflater(buf, 0, 1)
return buf[0] if n > 0 else -1
if off is None:
off = 0
if length is None:
length = len(b)
return self._read_from_inflater(b, off, length)
def _read_from_inflater(self, b, off, length):
while not self._inflater.finished():
if self._inflater.needsInput():
data = self._in.read(self._buffer)
if data is None or data == -1 or data == 0:
break
if isinstance(data, int):
break
self._inflater.setInput(data)
try:
n = self._inflater.inflate(b, off, length)
if n > 0:
return n
except DataFormatException:
break
return -1
def available(self):
return 0
def close(self):
self._inflater.end()
self._in.close()
def mark(self, readlimit):
pass
def reset(self):
raise IOException("mark/reset not supported")
def markSupported(self):
return False