001: /*
002: * Copyright 2001-2005 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.net.io;
017:
018: import java.io.FilterOutputStream;
019: import java.io.IOException;
020: import java.io.OutputStream;
021:
022: /***
023: * This class wraps an output stream, replacing all occurrences
024: * of <CR><LF> (carriage return followed by a linefeed),
025: * which is the NETASCII standard for representing a newline, with the
026: * local line separator representation. You would use this class to
027: * implement ASCII file transfers requiring conversion from NETASCII.
028: * <p>
029: * Because of the translation process, a call to <code>flush()</code> will
030: * not flush the last byte written if that byte was a carriage
031: * return. A call to {@link #close close() }, however, will
032: * flush the carriage return.
033: * <p>
034: * <p>
035: * @author Daniel F. Savarese
036: ***/
037:
038: public final class FromNetASCIIOutputStream extends FilterOutputStream {
039: private boolean __lastWasCR;
040:
041: /***
042: * Creates a FromNetASCIIOutputStream instance that wraps an existing
043: * OutputStream.
044: * <p>
045: * @param output The OutputStream to wrap.
046: ***/
047: public FromNetASCIIOutputStream(OutputStream output) {
048: super (output);
049: __lastWasCR = false;
050: }
051:
052: private void __write(int ch) throws IOException {
053: switch (ch) {
054: case '\r':
055: __lastWasCR = true;
056: // Don't write anything. We need to see if next one is linefeed
057: break;
058: case '\n':
059: if (__lastWasCR) {
060: out.write(FromNetASCIIInputStream._lineSeparatorBytes);
061: __lastWasCR = false;
062: break;
063: }
064: __lastWasCR = false;
065: out.write('\n');
066: break;
067: default:
068: if (__lastWasCR) {
069: out.write('\r');
070: __lastWasCR = false;
071: }
072: out.write(ch);
073: break;
074: }
075: }
076:
077: /***
078: * Writes a byte to the stream. Note that a call to this method
079: * might not actually write a byte to the underlying stream until a
080: * subsequent character is written, from which it can be determined if
081: * a NETASCII line separator was encountered.
082: * This is transparent to the programmer and is only mentioned for
083: * completeness.
084: * <p>
085: * @param ch The byte to write.
086: * @exception IOException If an error occurs while writing to the underlying
087: * stream.
088: ***/
089: public synchronized void write(int ch) throws IOException {
090: if (FromNetASCIIInputStream._noConversionRequired) {
091: out.write(ch);
092: return;
093: }
094:
095: __write(ch);
096: }
097:
098: /***
099: * Writes a byte array to the stream.
100: * <p>
101: * @param buffer The byte array to write.
102: * @exception IOException If an error occurs while writing to the underlying
103: * stream.
104: ***/
105: public synchronized void write(byte buffer[]) throws IOException {
106: write(buffer, 0, buffer.length);
107: }
108:
109: /***
110: * Writes a number of bytes from a byte array to the stream starting from
111: * a given offset.
112: * <p>
113: * @param buffer The byte array to write.
114: * @param offset The offset into the array at which to start copying data.
115: * @param length The number of bytes to write.
116: * @exception IOException If an error occurs while writing to the underlying
117: * stream.
118: ***/
119: public synchronized void write(byte buffer[], int offset, int length)
120: throws IOException {
121: if (FromNetASCIIInputStream._noConversionRequired) {
122: // FilterOutputStream method is very slow.
123: //super.write(buffer, offset, length);
124: out.write(buffer, offset, length);
125: return;
126: }
127:
128: while (length-- > 0)
129: __write(buffer[offset++]);
130: }
131:
132: /***
133: * Closes the stream, writing all pending data.
134: * <p>
135: * @exception IOException If an error occurs while closing the stream.
136: ***/
137: public synchronized void close() throws IOException {
138: if (FromNetASCIIInputStream._noConversionRequired) {
139: super .close();
140: return;
141: }
142:
143: if (__lastWasCR)
144: out.write('\r');
145: super.close();
146: }
147: }
|