dotterminatedmessagereader.java

来自「apache推出的net包」· Java 代码 · 共 274 行

JAVA
274
字号
/* * Copyright 2001-2005 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.commons.net.io;import java.io.IOException;import java.io.PushbackReader;import java.io.Reader;/** * DotTerminatedMessageReader is a class used to read messages from a * server that are terminated by a single dot followed by a * &lt;CR&gt;&lt;LF&gt; * sequence and with double dots appearing at the begining of lines which * do not signal end of message yet start with a dot.  Various Internet * protocols such as NNTP and POP3 produce messages of this type. * <p> * This class handles stripping of the duplicate period at the beginning * of lines starting with a period, converts NETASCII newlines to the * local line separator format, truncates the end of message indicator, * and ensures you cannot read past the end of the message. * @author <a href="mailto:savarese@apache.org">Daniel F. Savarese</a> * @version $Id: DotTerminatedMessageReader.java 165675 2005-05-02 20:09:55Z rwinston $ */public final class DotTerminatedMessageReader extends Reader{    private static final String LS;    private static final char[] LS_CHARS;    static    {        LS = System.getProperty("line.separator");        LS_CHARS = LS.toCharArray();    }    private boolean atBeginning;    private boolean eof;    private int pos;    private char[] internalBuffer;    private PushbackReader internalReader;    /**     * Creates a DotTerminatedMessageReader that wraps an existing Reader     * input source.     * @param reader  The Reader input source containing the message.     */    public DotTerminatedMessageReader(Reader reader)    {        super(reader);        internalBuffer = new char[LS_CHARS.length + 3];        pos = internalBuffer.length;        // Assumes input is at start of message        atBeginning = true;        eof = false;        internalReader = new PushbackReader(reader);    }    /**     * Reads and returns the next character in the message.  If the end of the     * message has been reached, returns -1.  Note that a call to this method     * may result in multiple reads from the underlying input stream to decode     * the message properly (removing doubled dots and so on).  All of     * this is transparent to the programmer and is only mentioned for     * completeness.     * @return The next character in the message. Returns -1 if the end of the     *          message has been reached.     * @exception IOException If an error occurs while reading the underlying     *            stream.     */    public int read() throws IOException    {        int ch;        synchronized (lock)        {            if (pos < internalBuffer.length)            {                return internalBuffer[pos++];            }            if (eof)            {                return -1;            }            if ((ch = internalReader.read()) == -1)            {                eof = true;                return -1;            }            if (atBeginning)            {                atBeginning = false;                if (ch == '.')                {                    ch = internalReader.read();                    if (ch != '.')                    {                        // read newline                        eof = true;                        internalReader.read();                        return -1;                    }                    else                    {                        return '.';                    }                }            }            if (ch == '\r')            {                ch = internalReader.read();                if (ch == '\n')                {                    ch = internalReader.read();                    if (ch == '.')                    {                        ch = internalReader.read();                        if (ch != '.')                        {                            // read newline and indicate end of file                            internalReader.read();                            eof = true;                        }                        else                        {                            internalBuffer[--pos] = (char) ch;                        }                    }                    else                    {                        internalReader.unread(ch);                    }                    pos -= LS_CHARS.length;                    System.arraycopy(LS_CHARS, 0, internalBuffer, pos,                                     LS_CHARS.length);                    ch = internalBuffer[pos++];                }                else                {                    internalBuffer[--pos] = (char) ch;                    return '\r';                }            }            return ch;        }    }    /**     * Reads the next characters from the message into an array and     * returns the number of characters read.  Returns -1 if the end of the     * message has been reached.     * @param buffer  The character array in which to store the characters.     * @return The number of characters read. Returns -1 if the     *          end of the message has been reached.     * @exception IOException If an error occurs in reading the underlying     *            stream.     */    public int read(char[] buffer) throws IOException    {        return read(buffer, 0, buffer.length);    }    /**     * Reads the next characters from the message into an array and     * returns the number of characters read.  Returns -1 if the end of the     * message has been reached.  The characters are stored in the array     * starting from the given offset and up to the length specified.     * @param buffer  The character array in which to store the characters.     * @param offset   The offset into the array at which to start storing     *              characters.     * @param length   The number of characters to read.     * @return The number of characters read. Returns -1 if the     *          end of the message has been reached.     * @exception IOException If an error occurs in reading the underlying     *            stream.     */    public int read(char[] buffer, int offset, int length) throws IOException    {        int ch, off;        synchronized (lock)        {            if (length < 1)            {                return 0;            }            if ((ch = read()) == -1)            {                return -1;            }            off = offset;            do            {                buffer[offset++] = (char) ch;            }            while (--length > 0 && (ch = read()) != -1);            return (offset - off);        }    }    /**     * Determines if the message is ready to be read.     * @return True if the message is ready to be read, false if not.     * @exception IOException If an error occurs while checking the underlying     *            stream.     */    public boolean ready() throws IOException    {        synchronized (lock)        {            return (pos < internalBuffer.length || internalReader.ready());        }    }    /**     * Closes the message for reading.  This doesn't actually close the     * underlying stream.  The underlying stream may still be used for     * communicating with the server and therefore is not closed.     * <p>     * If the end of the message has not yet been reached, this method     * will read the remainder of the message until it reaches the end,     * so that the underlying stream may continue to be used properly     * for communicating with the server.  If you do not fully read     * a message, you MUST close it, otherwise your program will likely     * hang or behave improperly.     * @exception IOException  If an error occurs while reading the     *            underlying stream.     */    public void close() throws IOException    {        synchronized (lock)        {            if (internalReader == null)            {                return;            }            if (!eof)            {                while (read() != -1)                {                    ;                }            }            eof = true;            atBeginning = false;            pos = internalBuffer.length;            internalReader = null;        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?