writestream.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,382 行 · 第 1/2 页
JAVA
1,382 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.vfs;import com.caucho.util.CharSegment;import com.caucho.vfs.i18n.EncodingWriter;import java.io.IOException;import java.io.InputStream;import java.io.PrintWriter;import java.io.Reader;import java.io.UnsupportedEncodingException;import java.io.Writer;import java.util.Iterator;import java.util.Locale;/** * A fast bufferered output stream supporting both character * and byte data. The underlying stream sources are provided by StreamImpl * classes, so all streams have the same API regardless of the underlying * implementation. * * <p>OutputStream and Writers are combined. The <code>write</code> routines * write bytes and the <code>print</code> routines write characters. * * <p>Most applications will use the Path routines to create their own streams. * Specialized applications, like servers, need the capability of recycling * streams. */public class WriteStream extends OutputStreamWithBuffer implements LockableStream{ private static byte []lfBytes = new byte[] {'\n'}; private static byte []crBytes = new byte[] {'\r'}; private static byte []crlfBytes = new byte[] {'\r', '\n'}; private static String _sysNewline; private static byte []_sysNewlineBytes; static { _sysNewline = Path.getNewlineString(); _sysNewlineBytes = _sysNewline.getBytes(); } private TempBuffer _tempWrite; private byte []_writeBuffer; private int _writeLength; private StreamImpl _source; private long _position; private char []chars; private byte []_bytes; private EncodingWriter _writeEncoding; private String _writeEncodingName; private boolean _implicitFlush = false; private boolean flushOnNewline; private boolean _disableClose; private boolean _isDisableCloseSource; private boolean _disableFlush; private boolean reuseBuffer; private StreamWriter _writer; private StreamPrintWriter _printWriter; private String newline = "\n"; private byte []newlineBytes = lfBytes; /** * Creates an uninitialized stream. Use <code>init</code> to initialize. */ public WriteStream() { } /** * Creates a stream and initializes with a specified source. * * @param source Underlying source for the stream. */ public WriteStream(StreamImpl source) { init(source); } /** * Initializes the stream with a given source. * * @param source Underlying source for the stream. */ public void init(StreamImpl source) { _disableClose = false; _isDisableCloseSource = false; if (this._source != null && this._source != source) { try { close(); } catch (IOException e) { } } if (source == null) throw new IllegalArgumentException(); if (_tempWrite == null) { _tempWrite = TempBuffer.allocate(); _writeBuffer = _tempWrite._buf; } this._source = source; _position = 0; _writeLength = 0; flushOnNewline = source.getFlushOnNewline(); // Possibly, this should be dependent on the source. For example, // a http: stream should behave the same on Mac as on unix. // For now, CauchoSystem.getNewlineString() returns "\n". newline = _sysNewline; newlineBytes = _sysNewlineBytes; _writeEncoding = null; _writeEncodingName = "ISO-8859-1"; } /** * Returns the underlying source for the stream. * * @return the source */ public StreamImpl getSource() { return _source; } /** * Pushes a filter on the top of the stream stack. * * @param filter the filter to be added. */ public void pushFilter(StreamFilter filter) { filter.init(_source); _source = filter; } /** * Returns true if the buffer allows writes. * * <p>LogStreams, used for debugging, use this feature to * test if they should write with very little overhead. * * <code><pre> * if (dbg.canWrite()) * dbg.log("some debug value " + expensiveDebugCalculation(foo)); * </pre></code> */ public boolean canWrite() { return _source != null && _source.canWrite(); } /** * Clears the write buffer */ public void clearWrite() { if (_source != null) _source.clearWrite(); } public void setReuseBuffer(boolean reuse) { this.reuseBuffer = reuse; } /** * Returns the write buffer. */ public byte []getBuffer() { return _writeBuffer; } /** * Returns the write offset. */ public int getBufferOffset() { return _writeLength; } /** * Sets the write offset. */ public void setBufferOffset(int offset) { _writeLength = offset; } /** * Returns the write size. */ public int getBufferSize() { return _writeBuffer.length; } /** * Returns the bytes remaining in the buffer. */ public int getRemaining() { if (_source == null) return 0; else return _writeBuffer.length - _writeLength; } public void setImplicitFlush(boolean implicitFlush) { _implicitFlush = implicitFlush; } /** * Writes a byte. */ public void write(int ch) throws IOException { if (_source == null) return; int len = _writeLength; if (_writeBuffer.length <= len) { _writeLength = 0; _source.write(_writeBuffer, 0, len, false); _position += len; } _writeBuffer[_writeLength++] = (byte) ch; if (_implicitFlush) flush(); } /** * Writes a byte array */ public void write(byte []buf, int offset, int length) throws IOException { byte []buffer = _writeBuffer; if (_source == null) return; int bufferLength = buffer.length; int writeLength = _writeLength; if (bufferLength <= length && _source.write(buffer, 0, writeLength, buf, offset, length, false)) { _position += (writeLength + length); return; } while (length > 0) { int sublen = bufferLength - writeLength; if (length < sublen) sublen = length; System.arraycopy(buf, offset, buffer, writeLength, sublen); writeLength += sublen; offset += sublen; length -= sublen; if (bufferLength <= writeLength) { int len = writeLength; writeLength = 0; _source.write(buffer, 0, len, false); _position += len; } } _writeLength = writeLength; if (_implicitFlush) flush(); } /** * Flushes and writes the buffer */ public byte []nextBuffer(int offset) throws IOException { _writeLength = 0; _source.write(_writeBuffer, 0, offset, false); _position += offset; if (_implicitFlush) flush(); return _writeBuffer; } /** * Writes a byte array. */ public void write(byte []buf) throws IOException { write(buf, 0, buf.length); } /** * Flushes the buffer to the source. */ public void flush() throws IOException { if (_disableFlush || _source == null) return; int len = _writeLength; if (len > 0) { _writeLength = 0; _source.write(_writeBuffer, 0, len, false); _position += len; } if (_source != null) _source.flush(); } /** * Flushes the buffer to the disk */ public void flushToDisk() throws IOException { StreamImpl source = _source; if (_disableFlush || source == null) return; int len = _writeLength; if (len > 0) { _writeLength = 0; source.write(_writeBuffer, 0, len, false); } source.flushToDisk(); } /** * Flushes the buffer to the source. */ public void flushBuffer() throws IOException { if (_disableFlush || _source == null) return; int len = _writeLength; if (len > 0) { _writeLength = 0; _source.write(_writeBuffer, 0, len, false); _position += len; _source.flushBuffer(); } } /** * Seeks based on the start */ public void seekStart(long pos) throws IOException { flushBuffer(); StreamImpl source = _source; if (source != null) { source.seekStart(pos); _position = pos; } } /** * Seeks based on the end */ public void seekEnd(long offset) throws IOException { flushBuffer(); StreamImpl source = _source; if (source != null) source.seekEnd(offset); // XXX : Don't know where end position is _position = offset; } /* * Writer methods */ /** * Sets the character encoding for writing to this stream. * Encoding can be a Java encoding or a mime-encoding. */ public void setEncoding(String encoding) throws UnsupportedEncodingException { if (_source instanceof ReaderWriterStream) encoding = "UTF-8"; String mimeName = Encoding.getMimeName(encoding); if (mimeName != null && mimeName.equals(_writeEncodingName)) return; if (_source != null) _source.setWriteEncoding(encoding); _writeEncoding = Encoding.getWriteEncoding(encoding); _writeEncodingName = mimeName; } public void setLocale(Locale locale) throws UnsupportedEncodingException { if (_writeEncoding == null && locale != null) setEncoding(Encoding.getMimeName(locale)); } /** * Returns the mime-encoding used for writing. */ public String getEncoding() { if (_source instanceof ReaderWriterStream) return ((ReaderWriterStream) _source).getEncoding(); else return _writeEncodingName; } public String getJavaEncoding() { return Encoding.getJavaName(getEncoding()); } /** * Some streams, like log streams, should be flushed on every println * call. Embedded newlines, i.e. '\n' in strings, do not trigger a * flush. * * @param flushOnNewline set to true if println flushes. */ public void setFlushOnNewline(boolean flushOnNewline) { this.flushOnNewline = flushOnNewline; } /** * Returns the current string used for println newlines */ public String getNewlineString() { return newline; } /** * Sets the string to use for println newlines */ public void setNewlineString(String newline) { if (newline != null) { if (this.newline == newline || newline.equals(this.newline)) { } else if (newline == "\n" || newline.equals("\n")) { this.newlineBytes = lfBytes; } else if (newline == "\r\n" || newline.equals("\r\n")) { this.newlineBytes = crlfBytes; } else if (newline == "\r" || newline.equals("\r")) { this.newlineBytes = crBytes; } else { this.newlineBytes = newline.getBytes(); } this.newline = newline; } } /** * Prints the character buffer to the stream. * * @param buffer character buffer to write * @param offset offset into the buffer to start writes * @param length number of characters to write */ public final void print(char []buffer, int offset, int length) throws IOException { byte []writeBuffer = this._writeBuffer; if (_source == null) return; if (_writeEncoding != null) { _disableFlush = true; _writeEncoding.write(this, buffer, offset, length); _disableFlush = false; return; } while (length > 0) { int writeLength = _writeLength; int sublen = writeBuffer.length - writeLength; if (sublen <= 0) { _source.write(writeBuffer, 0, writeLength, false); _position += writeLength; writeLength = 0; sublen = writeBuffer.length - writeLength; } if (length < sublen) sublen = length; for (int i = sublen - 1; i >= 0; i--) writeBuffer[writeLength + i] = (byte) buffer[offset + i]; _writeLength = writeLength + sublen; offset += sublen; length -= sublen; } if (_implicitFlush) flush(); } /** * Prints the character buffer to the stream. * * @param ch char */ public final void print(char ch) throws IOException { if (_writeEncoding != null) { _disableFlush = true; _writeEncoding.write(this, ch); _disableFlush = false; return; } write((byte) ch); } /** * Prints the character buffer to the stream. * * @param buffer character buffer to write */ public final void print(char []buffer) throws IOException { print(buffer, 0, buffer.length); } /** * Prints the character buffer to the stream. * * @param segment character buffer to write */ public final void print(CharSegment segment) throws IOException { print(segment.getBuffer(), segment.getOffset(), segment.getLength()); } /** * Prints a string. */ public final void print(String string) throws IOException { if (string == null) string = "null"; int length = string.length(); int offset = 0; while (length > 0) { int sublen = length < 1024 ? length : 1024; if (chars == null || chars.length < sublen) chars = new char[sublen < 32 ? 32 : sublen]; string.getChars(offset, offset + sublen, chars, 0); print(chars, 0, sublen); length -= sublen; offset += sublen; } } /** * Prints a substring. * * @param string the string to print * @param offset starting offset into the string * @param length length of the substring to print. */ public final void print(String string, int offset, int length) throws IOException { if (string == null) string = "null"; while (length > 0) { int sublen = length < 1024 ? length : 1024; if (chars == null || chars.length < sublen) chars = new char[sublen < 32 ? 32 : sublen]; string.getChars(offset, offset + sublen, chars, 0); print(chars, 0, sublen); length -= sublen; offset += sublen; } } /** * Prints a boolean. */ public final void print(boolean b) throws IOException { print(b ? "true" : "false"); } /** * Prints an integer. */ public final void print(int i) throws IOException { if (i == 0x80000000) { print("-2147483648"); return; } if (i < 0) { write('-'); i = -i; } else if (i < 9) { write('0' + i); return; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?