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 + -
显示快捷键?