View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.io;
19  
20  import java.io.FilterOutputStream;
21  import java.io.IOException;
22  import java.io.OutputStream;
23  
24  /***
25   * This class wraps an output stream, replacing all occurrences
26   * of <CR><LF> (carriage return followed by a linefeed),
27   * which is the NETASCII standard for representing a newline, with the
28   * local line separator representation.  You would use this class to
29   * implement ASCII file transfers requiring conversion from NETASCII.
30   * <p>
31   * Because of the translation process, a call to <code>flush()</code> will
32   * not flush the last byte written if that byte was a carriage
33   * return.  A call to {@link #close  close() }, however, will
34   * flush the carriage return.
35   * <p>
36   * <p>
37   * @author Daniel F. Savarese
38   ***/
39  
40  public final class FromNetASCIIOutputStream extends FilterOutputStream
41  {
42      private boolean __lastWasCR;
43  
44      /***
45       * Creates a FromNetASCIIOutputStream instance that wraps an existing
46       * OutputStream.
47       * <p>
48       * @param output  The OutputStream to wrap.
49       ***/
50      public FromNetASCIIOutputStream(OutputStream output)
51      {
52          super(output);
53          __lastWasCR = false;
54      }
55  
56  
57      private void __write(int ch) throws IOException
58      {
59          switch (ch)
60          {
61          case '\r':
62              __lastWasCR = true;
63              // Don't write anything.  We need to see if next one is linefeed
64              break;
65          case '\n':
66              if (__lastWasCR)
67              {
68                  out.write(FromNetASCIIInputStream._lineSeparatorBytes);
69                  __lastWasCR = false;
70                  break;
71              }
72              __lastWasCR = false;
73              out.write('\n');
74              break;
75          default:
76              if (__lastWasCR)
77              {
78                  out.write('\r');
79                  __lastWasCR = false;
80              }
81              out.write(ch);
82              break;
83          }
84      }
85  
86  
87      /***
88       * Writes a byte to the stream.    Note that a call to this method
89       * might not actually write a byte to the underlying stream until a
90       * subsequent character is written, from which it can be determined if
91       * a NETASCII line separator was encountered.
92       * This is transparent to the programmer and is only mentioned for
93       * completeness.
94       * <p>
95       * @param ch The byte to write.
96       * @exception IOException If an error occurs while writing to the underlying
97       *            stream.
98       ***/
99      @Override
100     public synchronized void write(int ch)
101     throws IOException
102     {
103         if (FromNetASCIIInputStream._noConversionRequired)
104         {
105             out.write(ch);
106             return ;
107         }
108 
109         __write(ch);
110     }
111 
112 
113     /***
114      * Writes a byte array to the stream.
115      * <p>
116      * @param buffer  The byte array to write.
117      * @exception IOException If an error occurs while writing to the underlying
118      *            stream.
119      ***/
120     @Override
121     public synchronized void write(byte buffer[])
122     throws IOException
123     {
124         write(buffer, 0, buffer.length);
125     }
126 
127 
128     /***
129      * Writes a number of bytes from a byte array to the stream starting from
130      * a given offset.
131      * <p>
132      * @param buffer  The byte array to write.
133      * @param offset  The offset into the array at which to start copying data.
134      * @param length  The number of bytes to write.
135      * @exception IOException If an error occurs while writing to the underlying
136      *            stream.
137      ***/
138     @Override
139     public synchronized void write(byte buffer[], int offset, int length)
140     throws IOException
141     {
142         if (FromNetASCIIInputStream._noConversionRequired)
143         {
144             // FilterOutputStream method is very slow.
145             //super.write(buffer, offset, length);
146             out.write(buffer, offset, length);
147             return ;
148         }
149 
150         while (length-- > 0)
151             __write(buffer[offset++]);
152     }
153 
154 
155     /***
156      * Closes the stream, writing all pending data.
157      * <p>
158      * @exception IOException  If an error occurs while closing the stream.
159      ***/
160     @Override
161     public synchronized void close()
162     throws IOException
163     {
164         if (FromNetASCIIInputStream._noConversionRequired)
165         {
166             super.close();
167             return ;
168         }
169 
170         if (__lastWasCR)
171             out.write('\r');
172         super.close();
173     }
174 }