Files
Android-pyApi/android_pyapi/java/io_ext.py
T
shuiyu1123 a51854455b feat: 大规模扩充至212个模块/175K行代码 — 覆盖android/java/javax/org/dalvik全包
- android/ 167个模块 (app/content/os/view/widget/graphics/media/hardware/net/telephony/provider等)
- java/ 35个模块 (lang/io/util/net/nio/security/crypto/sql/beans/rmi/awt等)
- javax/ 4个模块 (net/crypto/security/sql)
- org/ 5个模块 (json/w3c_dom/xml_sax/xml_pull/apache_http)
- dalvik/ 1个模块 (system)
- ~3053个类/接口,方法签名完全对齐Android SDK
- 桌面跨平台运行 (Windows/macOS/Linux)
- 修复所有导入错误和Python关键字冲突
2026-06-24 14:15:56 +00:00

1414 lines
39 KiB
Python

"""
Java java.io extended standard library APIs implemented in Python.
Extends java.io with ObjectStreamField, ObjectStreamConstants, ObjectInput, etc.
"""
from __future__ import annotations
from .._core import Stub
from ..java.io import (
Serializable, Externalizable, IOException,
ObjectStreamConstants as _BaseObjectStreamConstants,
File as _File, PrintWriter,
)
from ..java.lang import RuntimeException, String, Exception as _JavaException
import io as _pyio
import os as _os
import sys as _sys
import struct as _struct
import pickle as _pickle
import threading as _threading
import traceback as _traceback
import types as _py_types
__all__ = [
"ObjectStreamField", "ObjectStreamConstants",
"ObjectInput", "ObjectOutput", "ObjectInputStream", "ObjectOutputStream",
"ObjectStreamClass", "ObjectInputValidation",
"SerialCallbackContext",
"Externalizable", "Serializable",
"FileFilter", "FileNameFilter", "FilePermission",
"SerializablePermission",
"Console", "PrintStream",
"DataInput", "DataOutput",
"SequenceInputStream", "StringBufferInputStream",
"LineNumberReader", "CharArrayReader", "CharArrayWriter",
"FilterReader", "FilterWriter", "PushbackReader",
"PushbackInputStream", "StreamTokenizer",
"StreamCorruptedException", "WriteAbortedException",
]
# ============================================================
# ObjectStreamConstants
# ============================================================
class ObjectStreamConstants(Stub):
"""java.io.ObjectStreamConstants"""
STREAM_MAGIC = 0xACED
STREAM_VERSION = 5
TC_BASE = 0x70
TC_NULL = 0x70
TC_REFERENCE = 0x71
TC_CLASS = 0x72
TC_OBJECT = 0x73
TC_STRING = 0x74
TC_ARRAY = 0x75
TC_ENUM = 0x7E
TC_CLASSDESC = 0x72
TC_PROXYCLASSDESC = 0x7D
TC_BLOCKDATA = 0x77
TC_ENDBLOCKDATA = 0x78
TC_RESET = 0x79
TC_EXCEPTION = 0x7A
TC_LONGSTRING = 0x7C
baseWireHandle = 0x7E0000
PROTOCOL_VERSION_1 = 1
PROTOCOL_VERSION_2 = 2
SC_WRITE_METHOD = 0x01
SC_BLOCK_DATA = 0x08
SC_SERIALIZABLE = 0x02
SC_EXTERNALIZABLE = 0x04
SC_ENUM = 0x10
SUBSTITUTION_PERMISSION = "enableSubstitution"
# ============================================================
# ObjectStreamField
# ============================================================
class ObjectStreamField(Stub):
"""java.io.ObjectStreamField"""
def __init__(self, name, field_type, unshared=False):
super().__init__()
self._name = name
self._type = field_type
self._unshared = unshared
def getName(self):
return self._name
def getType(self):
return self._type
def getTypeString(self):
return self._type.__name__ if hasattr(self._type, '__name__') else str(self._type)
def getTypeCode(self):
return self.getTypeString()[0].upper()
def isUnshared(self):
return self._unshared
def isPrimitive(self):
return self._type in (int, float, bool, bytes, str, bytearray)
def toString(self):
return f"{self.getTypeString()} {self._name}"
# ============================================================
# ObjectStreamClass
# ============================================================
class ObjectStreamClass(Stub):
"""java.io.ObjectStreamClass"""
_descriptors = {}
def __init__(self, cls=None):
super().__init__()
self._cls = cls
self._name = cls.__name__ if cls else ""
self._serial_version_uid = hash(cls) if cls else 0
self._fields = []
self._serializable = hasattr(cls, '__getstate__') or hasattr(cls, '__setstate__') if cls else False
if cls:
for attr_name in dir(cls):
if not attr_name.startswith('_'):
attr_type = type(getattr(cls, attr_name, None))
self._fields.append(ObjectStreamField(attr_name, attr_type))
@staticmethod
def lookup(cls):
if cls is None:
return None
if cls not in ObjectStreamClass._descriptors:
ObjectStreamClass._descriptors[cls] = ObjectStreamClass(cls)
return ObjectStreamClass._descriptors[cls]
@staticmethod
def lookupAny(cls):
return ObjectStreamClass.lookup(cls)
def getName(self):
return self._name
def getSerialVersionUID(self):
return self._serial_version_uid
def getFields(self):
return self._fields
def getField(self, name):
for f in self._fields:
if f.getName() == name:
return f
return None
def forClass(self):
return self._cls
def isSerializable(self):
return self._serializable
def isEnum(self):
return False
def toString(self):
return f"ObjectStreamClass[{self._name}]"
# ============================================================
# ObjectInputValidation
# ============================================================
class ObjectInputValidation(Stub):
"""java.io.ObjectInputValidation"""
def validateObject(self):
raise NotImplementedError
# ============================================================
# SerialCallbackContext
# ============================================================
class SerialCallbackContext(Stub):
"""java.io.SerialCallbackContext"""
def __init__(self, obj, desc):
super().__init__()
self._obj = obj
self._desc = desc
self._used = False
def getObj(self):
return self._obj
def getDesc(self):
return self._desc
def setUsed(self):
self._used = True
def isUsed(self):
return self._used
# ============================================================
# ObjectInput / ObjectOutput interfaces
# ============================================================
class DataInput(Stub):
"""java.io.DataInput"""
def readByte(self):
raise NotImplementedError
def readShort(self):
raise NotImplementedError
def readInt(self):
raise NotImplementedError
def readLong(self):
raise NotImplementedError
def readFloat(self):
raise NotImplementedError
def readDouble(self):
raise NotImplementedError
def readBoolean(self):
raise NotImplementedError
def readChar(self):
raise NotImplementedError
def readUnsignedByte(self):
raise NotImplementedError
def readUnsignedShort(self):
raise NotImplementedError
def readUTF(self):
raise NotImplementedError
def readFully(self, b, off=0, length=-1):
raise NotImplementedError
def skipBytes(self, n):
raise NotImplementedError
def readLine(self):
raise NotImplementedError
class DataOutput(Stub):
"""java.io.DataOutput"""
def writeByte(self, v):
raise NotImplementedError
def writeShort(self, v):
raise NotImplementedError
def writeInt(self, v):
raise NotImplementedError
def writeLong(self, v):
raise NotImplementedError
def writeFloat(self, v):
raise NotImplementedError
def writeDouble(self, v):
raise NotImplementedError
def writeBoolean(self, v):
raise NotImplementedError
def writeChar(self, v):
raise NotImplementedError
def writeBytes(self, s):
raise NotImplementedError
def writeChars(self, s):
raise NotImplementedError
def writeUTF(self, s):
raise NotImplementedError
def write(self, b, off=0, length=-1):
raise NotImplementedError
class ObjectInput(DataInput):
"""java.io.ObjectInput"""
def readObject(self):
raise NotImplementedError
def available(self):
return 0
def close(self):
pass
class ObjectOutput(DataOutput):
"""java.io.ObjectOutput"""
def writeObject(self, obj):
raise NotImplementedError
def flush(self):
pass
def close(self):
pass
# ============================================================
# ObjectInputStream
# ============================================================
class ObjectInputStream(ObjectInput):
"""java.io.ObjectInputStream"""
def __init__(self, inp):
super().__init__()
self._input = inp
self._data = inp.read() if hasattr(inp, 'read') else b""
self._pos = 0
self._handles = {}
self._next_handle = ObjectStreamConstants.baseWireHandle
self._validation_list = []
self._resolved = {}
def readObject(self):
if self._pos >= len(self._data):
raise StreamCorruptedException("No data")
try:
obj = _pickle.loads(self._data[self._pos:])
return obj
except Exception:
return None
def readByte(self):
val = self._data[self._pos] if self._pos < len(self._data) else 0
self._pos += 1
return val
def readInt(self):
if self._pos + 4 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">i", self._data, self._pos)[0]
self._pos += 4
return val
def readShort(self):
if self._pos + 2 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">h", self._data, self._pos)[0]
self._pos += 2
return val
def readLong(self):
if self._pos + 8 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">q", self._data, self._pos)[0]
self._pos += 8
return val
def readFloat(self):
if self._pos + 4 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">f", self._data, self._pos)[0]
self._pos += 4
return val
def readDouble(self):
if self._pos + 8 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">d", self._data, self._pos)[0]
self._pos += 8
return val
def readBoolean(self):
return self.readByte() != 0
def readChar(self):
if self._pos + 2 > len(self._data):
raise StreamCorruptedException()
val = _struct.unpack_from(">H", self._data, self._pos)[0]
self._pos += 2
return chr(val)
def readUnsignedByte(self):
return self.readByte() & 0xFF
def readUnsignedShort(self):
return self.readShort() & 0xFFFF
def readUTF(self):
length = self.readUnsignedShort()
if self._pos + length > len(self._data):
raise StreamCorruptedException()
val = self._data[self._pos:self._pos + length].decode("utf-8")
self._pos += length
return val
def readFully(self, b, off=0, length=-1):
if length < 0:
length = len(b) - off
if self._pos + length > len(self._data):
raise StreamCorruptedException()
for i in range(length):
b[off + i] = self._data[self._pos + i]
self._pos += length
def skipBytes(self, n):
actual = min(n, len(self._data) - self._pos)
self._pos += actual
return actual
def readLine(self):
result = []
while self._pos < len(self._data):
c = chr(self._data[self._pos])
self._pos += 1
if c == "\n":
break
if c == "\r":
if self._pos < len(self._data) and chr(self._data[self._pos]) == "\n":
self._pos += 1
break
result.append(c)
return "".join(result)
def available(self):
return len(self._data) - self._pos
def close(self):
self._input = None
self._data = b""
self._pos = 0
def defaultReadObject(self):
return self.readObject()
def readFields(self):
return self.readObject()
def registerValidation(self, obj, prio):
self._validation_list.append((obj, prio))
def resolveClass(self, desc):
return desc.forClass()
def resolveObject(self, obj):
return obj
def enableResolveObject(self, enable):
return False
def readUnshared(self):
return self.readObject()
# ============================================================
# ObjectOutputStream
# ============================================================
class ObjectOutputStream(ObjectOutput):
"""java.io.ObjectOutputStream"""
def __init__(self, out):
super().__init__()
self._output = out
self._buffer = bytearray()
self._handles = {}
self._next_handle = ObjectStreamConstants.baseWireHandle
self._block_data_mode = False
self._extended_block_data_mode = False
def writeObject(self, obj):
data = _pickle.dumps(obj)
self._buffer.extend(data)
self._flush_buffer()
def writeByte(self, v):
self._buffer.extend(_struct.pack(">b", v if isinstance(v, int) else ord(v)))
def writeInt(self, v):
self._buffer.extend(_struct.pack(">i", int(v)))
def writeShort(self, v):
self._buffer.extend(_struct.pack(">h", int(v)))
def writeLong(self, v):
self._buffer.extend(_struct.pack(">q", int(v)))
def writeFloat(self, v):
self._buffer.extend(_struct.pack(">f", float(v)))
def writeDouble(self, v):
self._buffer.extend(_struct.pack(">d", float(v)))
def writeBoolean(self, v):
self._buffer.extend(_struct.pack(">?", bool(v)))
def writeChar(self, v):
if isinstance(v, str):
v = ord(v)
self._buffer.extend(_struct.pack(">H", int(v)))
def writeBytes(self, s):
if isinstance(s, str):
self._buffer.extend(s.encode())
elif isinstance(s, bytes):
self._buffer.extend(s)
elif isinstance(s, bytearray):
self._buffer.extend(s)
def writeChars(self, s):
for c in s:
self._buffer.extend(_struct.pack(">H", ord(c)))
def writeUTF(self, s):
encoded = s.encode("utf-8")
self.writeShort(len(encoded))
self._buffer.extend(encoded)
def write(self, b, off=0, length=-1):
if isinstance(b, int):
self._buffer.append(b & 0xFF)
elif isinstance(b, bytes):
if length < 0:
length = len(b) - off
self._buffer.extend(b[off:off + length])
elif isinstance(b, bytearray):
if length < 0:
length = len(b) - off
self._buffer.extend(b[off:off + length])
def flush(self):
self._flush_buffer()
if hasattr(self._output, 'flush'):
self._output.flush()
def close(self):
self.flush()
if hasattr(self._output, 'close'):
self._output.close()
def defaultWriteObject(self):
pass
def putFields(self):
return self
def writeFields(self):
pass
def reset(self):
self._handles = {}
self._next_handle = ObjectStreamConstants.baseWireHandle
self._buffer = bytearray()
def useProtocolVersion(self, version):
pass
def writeUnshared(self, obj):
self.writeObject(obj)
def annotateClass(self, cls):
pass
def annotateProxyClass(self, cls):
pass
def replaceObject(self, obj):
return obj
def enableReplaceObject(self, enable):
return False
def writeStreamHeader(self):
self._buffer.extend(_struct.pack(">HH",
ObjectStreamConstants.STREAM_MAGIC,
ObjectStreamConstants.STREAM_VERSION))
def _flush_buffer(self):
if self._buffer:
data = bytes(self._buffer)
if hasattr(self._output, 'write'):
self._output.write(data)
self._buffer = bytearray()
# ============================================================
# StreamCorruptedException / WriteAbortedException
# ============================================================
class StreamCorruptedException(IOException):
"""java.io.StreamCorruptedException"""
def __init__(self, message=None):
super().__init__(message or "Stream corrupted")
class WriteAbortedException(IOException):
"""java.io.WriteAbortedException"""
def __init__(self, message, exception):
super().__init__(message)
self._exception = exception
def getException(self):
return self._exception
# ============================================================
# FileFilter / FileNameFilter
# ============================================================
class FileFilter(Stub):
"""java.io.FileFilter"""
def accept(self, pathname):
return True
class FileNameFilter(Stub):
"""java.io.FilenameFilter"""
def accept(self, dir, name):
return True
# ============================================================
# FilePermission / SerializablePermission
# ============================================================
class FilePermission(Stub):
"""java.io.FilePermission"""
def __init__(self, path, actions):
super().__init__()
self._path = path
self._actions = actions
def getName(self):
return self._path
def getActions(self):
return self._actions
def implies(self, permission):
return True
def equals(self, other):
if not isinstance(other, FilePermission):
return False
return self._path == other._path and self._actions == other._actions
def hashCode(self):
return hash((self._path, self._actions))
class SerializablePermission(Stub):
"""java.io.SerializablePermission"""
def __init__(self, name, actions=None):
super().__init__()
self._name = name
self._actions = actions or ""
def getName(self):
return self._name
def getActions(self):
return self._actions
def implies(self, permission):
return True
# ============================================================
# Console
# ============================================================
class Console(Stub):
"""java.io.Console"""
def __init__(self):
super().__init__()
@staticmethod
def console():
return Console()
def readLine(self, fmt=None, *args):
if fmt:
print(fmt % args, end="")
return input()
def readPassword(self, fmt=None, *args):
import getpass
if fmt:
print(fmt % args, end="")
return getpass.getpass("")
def format(self, fmt, *args):
_sys.stdout.write(fmt % args)
_sys.stdout.flush()
return self
def printf(self, format, *args):
return self.format(format, *args)
def flush(self):
_sys.stdout.flush()
def reader(self):
return _pyio.BufferedReader(_pyio.FileIO(_sys.stdin.fileno()))
def writer(self):
return _pyio.TextIOWrapper(_pyio.BufferedWriter(
_pyio.FileIO(_sys.stdout.fileno(), "w")
))
# ============================================================
# PrintStream
# ============================================================
class PrintStream(Stub):
"""java.io.PrintStream"""
def __init__(self, out=None, auto_flush=False, encoding=None):
super().__init__()
self._out = out or _sys.stdout
self._auto_flush = auto_flush
self._encoding = encoding or "utf-8"
self._error = False
def print(self, obj=""):
_sys.stdout.write(str(obj))
def println(self, obj=""):
print(str(obj))
def printf(self, format, *args):
_sys.stdout.write(format % args)
if self._auto_flush:
_sys.stdout.flush()
return self
def format(self, format_, *args):
return self.printf(format_, *args)
def write(self, b, off=0, length=-1):
if isinstance(b, int):
self._out.write(bytes([b]))
elif isinstance(b, bytes):
if length < 0:
self._out.write(b[off:])
else:
self._out.write(b[off:off + length])
elif isinstance(b, str):
self._out.write(b)
if self._auto_flush:
self._out.flush()
def flush(self):
self._out.flush()
def close(self):
self.flush()
def checkError(self):
return self._error
def setError(self):
self._error = True
def clearError(self):
self._error = False
def append(self, c):
if isinstance(c, str):
self._out.write(c)
else:
self._out.write(str(c))
return self
# ============================================================
# SequenceInputStream
# ============================================================
class SequenceInputStream(Stub):
"""java.io.SequenceInputStream"""
def __init__(self, *args):
super().__init__()
if len(args) == 1:
self._enumerator = iter(args[0])
self._current = next(self._enumerator, None)
elif len(args) == 2:
self._enumerator = iter(args)
self._current = args[0]
else:
self._enumerator = iter([])
self._current = None
def read(self, b=None, off=0, length=-1):
while self._current is not None:
if hasattr(self._current, 'read'):
if b is None:
data = self._current.read()
else:
if length < 0:
data = self._current.read(len(b) - off)
else:
data = self._current.read(min(length, len(b) - off))
if data:
if b is not None:
for i, byte in enumerate(data):
b[off + i] = byte
return len(data)
self._current = next(self._enumerator, None)
else:
self._current = next(self._enumerator, None)
return -1
def close(self):
self._current = None
# ============================================================
# StringBufferInputStream
# ============================================================
class StringBufferInputStream(Stub):
"""java.io.StringBufferInputStream"""
def __init__(self, s):
super().__init__()
self._string = s
self._pos = 0
self._count = len(s)
def read(self, b=None, off=0, length=-1):
if self._pos >= self._count:
return -1
if b is None:
val = ord(self._string[self._pos]) if self._pos < self._count else -1
self._pos += 1
return val
if length < 0:
length = len(b) - off
available = self._count - self._pos
to_read = min(available, length)
for i in range(to_read):
b[off + i] = ord(self._string[self._pos + i])
self._pos += to_read
return to_read
def available(self):
return self._count - self._pos
def reset(self):
self._pos = 0
# ============================================================
# LineNumberReader
# ============================================================
class LineNumberReader(Stub):
"""java.io.LineNumberReader"""
def __init__(self, reader, sz=8192):
super().__init__()
self._reader = reader
self._line_number = 0
self._buffer = ""
self._pos = 0
self._marked_pos = 0
self._marked_line = 0
self._sz = sz
def readLine(self):
result = []
while self._pos < len(self._buffer) or self._fill_buffer():
if self._pos < len(self._buffer):
c = self._buffer[self._pos]
self._pos += 1
if c == "\n":
self._line_number += 1
return "".join(result)
if c == "\r":
self._line_number += 1
if self._pos < len(self._buffer) and self._buffer[self._pos] == "\n":
self._pos += 1
return "".join(result)
result.append(c)
else:
break
if not result:
return None
return "".join(result)
def getLineNumber(self):
return self._line_number
def setLineNumber(self, line_number):
self._line_number = line_number
def read(self, cbuf=None, off=0, length=-1):
if cbuf is None:
if self._pos < len(self._buffer) or self._fill_buffer():
if self._pos < len(self._buffer):
c = self._buffer[self._pos]
self._pos += 1
return ord(c)
return -1
count = 0
while count < (length if length >= 0 else len(cbuf) - off):
if self._pos >= len(self._buffer) and not self._fill_buffer():
break
cbuf[off + count] = self._buffer[self._pos]
self._pos += 1
count += 1
return count if count > 0 else -1
def close(self):
if self._reader and hasattr(self._reader, 'close'):
self._reader.close()
def mark(self, read_ahead_limit):
self._marked_pos = self._pos
self._marked_line = self._line_number
def reset(self):
self._pos = self._marked_pos
self._line_number = self._marked_line
def skip(self, n):
actual = 0
while actual < n:
if self._pos >= len(self._buffer) and not self._fill_buffer():
break
self._pos += 1
actual += 1
return actual
def ready(self):
return self._pos < len(self._buffer)
def _fill_buffer(self):
if self._reader and hasattr(self._reader, 'read'):
data = self._reader.read(self._sz)
if isinstance(data, str):
self._buffer = data
elif isinstance(data, bytes):
self._buffer = data.decode('utf-8')
else:
self._buffer = ""
self._pos = 0
return len(self._buffer) > 0
return False
# ============================================================
# CharArrayReader / CharArrayWriter
# ============================================================
class CharArrayReader(Stub):
"""java.io.CharArrayReader"""
def __init__(self, buf, offset=0, length=None):
super().__init__()
self._buf = list(buf)
if length is not None:
self._buf = self._buf[offset:offset + length]
else:
self._buf = self._buf[offset:]
self._pos = 0
self._marked_pos = 0
def read(self, cbuf=None, off=0, length=-1):
if self._pos >= len(self._buf):
return -1
if cbuf is None:
val = ord(self._buf[self._pos]) if isinstance(self._buf[self._pos], str) else self._buf[self._pos]
self._pos += 1
return val
if length < 0:
length = len(cbuf) - off
available = len(self._buf) - self._pos
to_read = min(available, length)
for i in range(to_read):
cbuf[off + i] = (
ord(self._buf[self._pos + i])
if isinstance(self._buf[self._pos + i], str)
else self._buf[self._pos + i]
)
self._pos += to_read
return to_read
def close(self):
self._buf = []
def mark(self, read_ahead_limit):
self._marked_pos = self._pos
def reset(self):
self._pos = self._marked_pos
def skip(self, n):
actual = min(n, len(self._buf) - self._pos)
self._pos += actual
return actual
def ready(self):
return self._pos < len(self._buf)
class CharArrayWriter(Stub):
"""java.io.CharArrayWriter"""
def __init__(self, initial_size=32):
super().__init__()
self._buf = []
def write(self, c, off=0, length=-1):
if isinstance(c, str):
self._buf.append(c)
elif isinstance(c, (list, tuple)):
if length < 0:
length = len(c) - off
self._buf.extend(c[off:off + length])
elif isinstance(c, int):
self._buf.append(chr(c))
def writeTo(self, out):
if hasattr(out, 'write'):
out.write(self.toString())
def toString(self):
return "".join(str(x) for x in self._buf)
def size(self):
return len(self._buf)
def toCharArray(self):
return list(self.toString())
def flush(self):
pass
def close(self):
pass
def reset(self):
self._buf = []
# ============================================================
# FilterReader / FilterWriter
# ============================================================
class FilterReader(Stub):
"""java.io.FilterReader"""
def __init__(self, reader):
super().__init__()
self._reader = reader
def read(self, cbuf=None, off=0, length=-1):
if self._reader:
return self._reader.read(cbuf, off, length)
return -1
def close(self):
if self._reader:
self._reader.close()
def mark(self, read_limit):
if self._reader and hasattr(self._reader, 'mark'):
self._reader.mark(read_limit)
def reset(self):
if self._reader and hasattr(self._reader, 'reset'):
self._reader.reset()
def ready(self):
if self._reader and hasattr(self._reader, 'ready'):
return self._reader.ready()
return False
def skip(self, n):
if self._reader and hasattr(self._reader, 'skip'):
return self._reader.skip(n)
return 0
class FilterWriter(Stub):
"""java.io.FilterWriter"""
def __init__(self, writer):
super().__init__()
self._writer = writer
def write(self, c, off=0, length=-1):
if self._writer:
if isinstance(c, str):
self._writer.write(c)
elif isinstance(c, int):
self._writer.write(chr(c))
def flush(self):
if self._writer:
self._writer.flush()
def close(self):
if self._writer:
self._writer.close()
# ============================================================
# PushbackReader
# ============================================================
class PushbackReader(FilterReader):
"""java.io.PushbackReader"""
def __init__(self, reader, size=1):
super().__init__(reader)
self._pushback_buf = []
self._pushback_size = size
def read(self, cbuf=None, off=0, length=-1):
if self._pushback_buf:
ch = self._pushback_buf.pop()
if cbuf is None:
return ord(ch) if isinstance(ch, str) else ch
cbuf[off] = ord(ch) if isinstance(ch, str) else ch
return 1
return super().read(cbuf, off, length)
def unread(self, c):
if len(self._pushback_buf) >= self._pushback_size:
raise IOException("Pushback buffer full")
if isinstance(c, (list, tuple)):
for ch in reversed(c):
self._pushback_buf.append(ch)
else:
self._pushback_buf.append(c)
# ============================================================
# PushbackInputStream
# ============================================================
class PushbackInputStream(Stub):
"""java.io.PushbackInputStream"""
def __init__(self, inp, size=1):
super().__init__()
self._input = inp
self._pushback_buf = bytearray()
self._pushback_size = size
def read(self, b=None, off=0, length=-1):
if self._pushback_buf and b is None:
return self._pushback_buf.pop(0)
if b is not None:
count = 0
while count < (length if length >= 0 else len(b) - off):
if self._pushback_buf:
b[off + count] = self._pushback_buf.pop(0)
elif self._input:
val = self._input.read(1)
if val == -1 or val == b"" or val is None:
break
b[off + count] = val[0] if isinstance(val, bytes) else val
else:
break
count += 1
return count if count > 0 else -1
if self._pushback_buf:
return self._pushback_buf.pop(0)
if self._input:
val = self._input.read(1)
if val is not None and val != -1:
return val[0] if isinstance(val, bytes) else val
return -1
def unread(self, b, off=0, length=-1):
if isinstance(b, int):
if len(self._pushback_buf) >= self._pushback_size:
raise IOException("Pushback buffer full")
self._pushback_buf.insert(0, b & 0xFF)
elif isinstance(b, (bytes, bytearray)):
if length < 0:
length = len(b) - off
if len(self._pushback_buf) + length > self._pushback_size:
raise IOException("Pushback buffer full")
for i in range(length - 1, -1, -1):
self._pushback_buf.insert(0, b[off + i])
def available(self):
return len(self._pushback_buf) + (self._input.available() if self._input else 0)
def close(self):
if self._input:
self._input.close()
self._pushback_buf = bytearray()
# ============================================================
# StreamTokenizer
# ============================================================
class StreamTokenizer(Stub):
"""java.io.StreamTokenizer"""
def __init__(self, reader=None, inp=None):
super().__init__()
if reader:
self._reader = reader
elif inp:
import io
self._reader = io.TextIOWrapper(io.BufferedReader(inp))
else:
self._reader = None
self.ttype = 0
self.sval = None
self.nval = 0.0
self._reset_syntax()
def _reset_syntax(self):
self._ordinary_chars = set()
self._word_chars = set()
self._whitespace_chars = set(range(0x20))
self._comment_char = None
self._quote_char = None
self._parse_numbers = True
self._lower_case_mode = False
self._slash_slash_comments = False
self._slash_star_comments = False
self._eol_is_significant = False
self._lower_case_mode = False
self._pushback = None
def resetSyntax(self):
self._reset_syntax()
def wordChars(self, low, high):
for c in range(low, high + 1):
self._word_chars.add(c)
def whitespaceChars(self, low, high):
for c in range(low, high + 1):
self._whitespace_chars.add(c)
def ordinaryChars(self, low, high):
for c in range(low, high + 1):
self._ordinary_chars.add(c)
def ordinaryChar(self, ch):
self._ordinary_chars.add(ch)
def commentChar(self, ch):
self._comment_char = ch
def quoteChar(self, ch):
self._quote_char = ch
def parseNumbers(self):
self._parse_numbers = True
def eolIsSignificant(self, flag):
self._eol_is_significant = flag
def slashSlashComments(self, flag):
self._slash_slash_comments = flag
def slashStarComments(self, flag):
self._slash_star_comments = flag
def lowerCaseMode(self, flag):
self._lower_case_mode = flag
def pushBack(self):
self._pushback = self.ttype
def lineno(self):
return 1
def toString(self):
if self.ttype == -1:
return "EOF"
if self.ttype == -3:
return f"WORD={self.sval}"
if self.ttype == -2:
return f"NUMBER={self.nval}"
return f"CHAR={chr(self.ttype) if self.ttype < 256 else '?'}"
def nextToken(self):
if self._pushback is not None:
pb = self._pushback
self._pushback = None
self.ttype = pb
return self.ttype
if self._reader is None:
self.ttype = -1 # TT_EOF
return -1
ch = self._read_char()
if ch is None:
self.ttype = -1
return -1
# Check for newlines
if ch == "\n":
if self._eol_is_significant:
self.ttype = 10 # TT_EOL
return 10
return self.nextToken()
# Whitespace
if ord(ch) in self._whitespace_chars:
return self.nextToken()
# Comment char
if self._comment_char is not None and ord(ch) == self._comment_char:
while ch is not None and ch != "\n":
ch = self._read_char()
return self.nextToken()
# Quote char
if self._quote_char is not None and ord(ch) == self._quote_char:
buf = []
while True:
ch = self._read_char()
if ch is None or ord(ch) == self._quote_char:
break
buf.append(ch)
self.sval = "".join(buf)
if self._lower_case_mode:
self.sval = self.sval.lower()
self.ttype = ord(self._quote_char)
return self.ttype
# Number
if self._parse_numbers and (ch.isdigit() or ch in ('-', '.')):
buf = [ch]
if ch in ('-', '.'):
next_ch = self._peek_char()
if next_ch is not None and (next_ch.isdigit() or next_ch == '.'):
buf.append(self._read_char())
while True:
ch = self._read_char()
if ch is None or not (ch.isdigit() or ch == '.' or ch in ('e', 'E', '-', '+')):
if ch is not None:
self._unread_char(ch)
break
buf.append(ch)
num_str = "".join(buf)
try:
self.nval = float(num_str)
except ValueError:
self.nval = 0.0
self.ttype = -2 # TT_NUMBER
return -2
# Word chars
if ord(ch) in self._word_chars:
buf = [ch]
while True:
next_ch = self._peek_char()
if next_ch is not None and ord(next_ch) in self._word_chars:
buf.append(self._read_char())
else:
break
self.sval = "".join(buf)
if self._lower_case_mode:
self.sval = self.sval.lower()
self.ttype = -3 # TT_WORD
return -3
# Ordinary char
self.ttype = ord(ch)
return ord(ch)
def _read_char(self):
if self._reader is None:
return None
try:
if hasattr(self._reader, 'read'):
c = self._reader.read(1)
if c and isinstance(c, bytes):
c = c.decode('utf-8')
return c if c else None
return None
except Exception:
return None
def _peek_char(self):
if self._reader is None:
return None
try:
c = self._reader.read(1)
if c and isinstance(c, bytes):
c = c.decode('utf-8')
if c:
self._unread_char(c)
return c if c else None
except Exception:
return None
def _unread_char(self, c):
if hasattr(self._reader, 'seek'):
self._reader.seek(self._reader.tell() - 1)
TT_EOF = -1
TT_EOL = 10
TT_NUMBER = -2
TT_WORD = -3