📄 pyfile.java
字号:
// Copyright (c) Corporation for National Research Initiativespackage org.python.core;import java.io.*;// To do:// - readinto(array)// - modes w, a should disallow reading// - what to do about buffer size?// - isatty()// - fileno() (defined, but always raises an exception, for urllib)// - name, mode, closed should be read-only/** * A python file wrapper around a java stream, reader/writer or file. */public class PyFile extends PyObject{ private static class FileWrapper { protected boolean reading; protected boolean writing; protected boolean binary; void setMode(String mode) { reading = mode.indexOf('r') >= 0; writing = mode.indexOf('w') >= 0 || mode.indexOf("+") >= 0 || mode.indexOf('a') >= 0; binary = mode.indexOf('b') >= 0; } public String read(int n) throws java.io.IOException { throw new java.io.IOException("file not open for reading"); } public int read() throws java.io.IOException { throw new java.io.IOException("file not open for reading"); } public int available() throws java.io.IOException { throw new java.io.IOException("file not open for reading"); } public void unread(int c) throws java.io.IOException { throw new java.io.IOException("file doesn't support unread"); } public void write(String s) throws java.io.IOException { throw new java.io.IOException("file not open for writing"); } public long tell() throws java.io.IOException { throw new java.io.IOException("file doesn't support tell/seek"); } public void seek(long pos, int how) throws java.io.IOException { throw new java.io.IOException("file doesn't support tell/seek"); } public void flush() throws java.io.IOException { } public void close() throws java.io.IOException { } public void truncate(long position) throws java.io.IOException { throw new java.io.IOException("file doesn't support truncate"); } public Object __tojava__(Class cls) throws IOException { return null; } protected byte[] getBytes(String s) { // Yes, I known the method is depricated, but it is the fastest // way of converting between between byte[] and String if (binary) { byte[] buf = new byte[s.length()]; s.getBytes(0, s.length(), buf, 0); return buf; } else return s.getBytes(); } protected String getString(byte[] buf, int offset, int len) { // Yes, I known the method is depricated, but it is the fastest // way of converting between between byte[] and String if (binary) { return new String(buf, 0, offset, len); } else return new String(buf, offset, len); } } private static class InputStreamWrapper extends FileWrapper { java.io.InputStream istream; public InputStreamWrapper(java.io.InputStream s) { istream = s; } public String read(int n) throws java.io.IOException { if (n == 0) // nothing to do return ""; if (n < 0) { // read until we hit EOF byte buf[] = new byte[1024]; StringBuffer sbuf = new StringBuffer(); for (int read=0; read >= 0; read=istream.read(buf)) sbuf.append(getString(buf, 0, read)); return sbuf.toString(); } // read the next chunk available, but make sure it's at least // one byte so as not to trip the `empty string' return value // test done by the caller int avail = istream.available(); //n = (n > avail) ? n : avail; byte buf[] = new byte[n]; int read = istream.read(buf); if (read < 0) // EOF encountered return ""; return new String(buf, 0, 0, read); } public int read() throws java.io.IOException { return istream.read(); } public int available() throws java.io.IOException { return istream.available(); } public void unread(int c) throws java.io.IOException { ((java.io.PushbackInputStream)istream).unread(c); } public void close() throws java.io.IOException { istream.close(); } public Object __tojava__(Class cls) throws IOException { if (InputStream.class.isAssignableFrom(cls)) return istream; return null; } } private static class OutputStreamWrapper extends FileWrapper { private java.io.OutputStream ostream; public OutputStreamWrapper(java.io.OutputStream s) { ostream = s; } private static final int MAX_WRITE = 30000; public void write(String s) throws java.io.IOException { byte[] bytes = getBytes(s); int n = bytes.length; int i = 0; while (i < n) { int sz = n-i; sz = sz > MAX_WRITE ? MAX_WRITE : sz; ostream.write(bytes, i, sz); i += sz; } } public void flush() throws java.io.IOException { ostream.flush(); } public void close() throws java.io.IOException { ostream.close(); } public Object __tojava__(Class cls) throws IOException { if (OutputStream.class.isAssignableFrom(cls)) return ostream; return null; } } private static class IOStreamWrapper extends InputStreamWrapper { private java.io.OutputStream ostream; public IOStreamWrapper(java.io.InputStream istream, java.io.OutputStream ostream) { super(istream); this.ostream = ostream; } public void write(String s) throws java.io.IOException { ostream.write(getBytes(s)); } public void flush() throws java.io.IOException { ostream.flush(); } public void close() throws java.io.IOException { ostream.close(); istream.close(); } public Object __tojava__(Class cls) throws IOException { if (OutputStream.class.isAssignableFrom(cls)) return ostream; return super.__tojava__(cls); } } private static class WriterWrapper extends FileWrapper { private java.io.Writer writer; public WriterWrapper(java.io.Writer s) { writer = s; } private static final int MAX_WRITE = 30000; public void write(String s) throws java.io.IOException { writer.write(s); } public void flush() throws java.io.IOException { writer.flush(); } public void close() throws java.io.IOException { writer.close(); } } private static class RFileWrapper extends FileWrapper { /** The default buffer size, in bytes. */ protected static final int defaultBufferSize = 4096; /** The underlying java.io.RandomAccessFile. */ protected java.io.RandomAccessFile file; /** The offset in bytes from the file start, of the next read or * write operation. */ protected long filePosition; /** The buffer used to load the data. */ protected byte buffer[]; /** The offset in bytes of the start of the buffer, from the start * of the file. */ protected long bufferStart; /** The offset in bytes of the end of the data in the buffer, from * the start of the file. This can be calculated from * <code>bufferStart + dataSize</code>, but it is cached to speed * up the read( ) method. */ protected long dataEnd; /** The size of the data stored in the buffer, in bytes. This may be * less than the size of the buffer.*/ protected int dataSize; /** True if we are at the end of the file. */ protected boolean endOfFile; /** True if the data in the buffer has been modified. */ boolean bufferModified = false; public RFileWrapper(java.io.RandomAccessFile file) { this(file, 8092); } public RFileWrapper(java.io.RandomAccessFile file, int bufferSize) { this.file = file; bufferStart = 0; dataEnd = 0; dataSize = 0; filePosition = 0; buffer = new byte[bufferSize]; endOfFile = false; } public String read(int n) throws java.io.IOException { if (n < 0) { n = (int)(file.length() - filePosition); if (n < 0) n = 0; } byte[] buf = new byte[n]; n = readBytes(buf, 0, n); if (n < 0) n = 0; return getString(buf, 0, n); } private int readBytes( byte b[], int off, int len ) throws IOException { // Check for end of file. if( endOfFile ) return -1; // See how many bytes are available in the buffer - if none, // seek to the file position to update the buffer and try again. int bytesAvailable = (int)(dataEnd - filePosition); if (bytesAvailable < 1) { seek(filePosition, 0); return readBytes( b, off, len ); } // Copy as much as we can. int copyLength = (bytesAvailable >= len) ? len : bytesAvailable; System.arraycopy(buffer, (int)(filePosition - bufferStart), b, off, copyLength); filePosition += copyLength; // If there is more to copy... if (copyLength < len) { int extraCopy = len - copyLength; // If the amount remaining is more than a buffer's // length, read it directly from the file. if (extraCopy > buffer.length) { file.seek(filePosition); extraCopy = file.read(b, off + copyLength, len - copyLength); } else { // ...or read a new buffer full, and copy as much // as possible... seek(filePosition, 0); if (!endOfFile) { extraCopy = (extraCopy > dataSize) ? dataSize : extraCopy; System.arraycopy(buffer, 0, b, off + copyLength, extraCopy); } else { extraCopy = -1; } } // If we did manage to copy any more, update the file // position and return the amount copied. if (extraCopy > 0) { filePosition += extraCopy; return copyLength + extraCopy; } } // Return the amount copied. return copyLength; } public int read() throws java.io.IOException { // If the file position is within the data, return the byte... if (filePosition < dataEnd) { return (int)(buffer[(int)(filePosition++ - bufferStart)] & 0xff); } else if (endOfFile) { // ...or should we indicate EOF... return -1; } else { // ...or seek to fill the buffer, and try again. seek(filePosition, 0); return read(); } } public int available() throws java.io.IOException { return 1; } public void unread(int c) throws java.io.IOException { filePosition--; } public void write(String s) throws java.io.IOException { byte[] b = getBytes(s); int len = b.length; // If the amount of data is small (less than a full buffer)... if (len < buffer.length) { // If any of the data fits within the buffer... int spaceInBuffer = 0; int copyLength = 0; if (filePosition >= bufferStart) spaceInBuffer = (int)((bufferStart + buffer.length) - filePosition); if (spaceInBuffer > 0) { // Copy as much as possible to the buffer. copyLength = (spaceInBuffer > len) ? len : spaceInBuffer; System.arraycopy(b, 0, buffer, (int)(filePosition - bufferStart), copyLength ); bufferModified = true; long myDataEnd = filePosition + copyLength; dataEnd = myDataEnd > dataEnd ? myDataEnd : dataEnd; dataSize = (int)(dataEnd - bufferStart); filePosition += copyLength; } // If there is any data remaining, move to the // new position and copy to the new buffer. if (copyLength < len) { seek(filePosition, 0); System.arraycopy(b, copyLength, buffer, (int)(filePosition - bufferStart), len - copyLength); bufferModified = true; long myDataEnd = filePosition + (len - copyLength); dataEnd = myDataEnd > dataEnd ? myDataEnd : dataEnd; dataSize = (int)(dataEnd - bufferStart); filePosition += (len - copyLength); } } else { // ...or write a lot of data... // Flush the current buffer, and write this data to the file. if (bufferModified) { flush( ); bufferStart = dataEnd = dataSize = 0; } file.write( b, 0, len ); filePosition += len; } } public long tell() throws java.io.IOException { return filePosition; } public void seek(long pos, int how) throws java.io.IOException { if (how == 1) pos += filePosition; else if (how == 2) pos += file.length(); if (pos < 0) pos = 0; // If the seek is into the buffer, just update the file pointer. if (pos >= bufferStart && pos < dataEnd) { filePosition = pos; endOfFile = false; return; } // If the current buffer is modified, write it to disk. if (bufferModified) flush(); // Move to the position on the disk. file.seek(pos); filePosition = file.getFilePointer(); bufferStart = filePosition; // Fill the buffer from the disk. dataSize = file.read(buffer); if (dataSize < 0) { dataSize = 0; endOfFile = true; } else { endOfFile = false; } // Cache the position of the buffer end. dataEnd = bufferStart + dataSize; } public void flush() throws java.io.IOException { file.seek(bufferStart); file.write(buffer, 0, dataSize); bufferModified = false; file.getFD().sync(); } public void close() throws java.io.IOException { if (writing && bufferModified) { file.seek(bufferStart); file.write(buffer, 0, (int)dataSize); } file.close(); } public void truncate(long position) throws java.io.IOException { flush(); try {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -