1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.net.io;
17
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.PushbackInputStream;
21
22 /***
23 * This class wraps an input stream, replacing all occurrences
24 * of <CR><LF> (carriage return followed by a linefeed),
25 * which is the NETASCII standard for representing a newline, with the
26 * local line separator representation. You would use this class to
27 * implement ASCII file transfers requiring conversion from NETASCII.
28 * <p>
29 * <p>
30 * @author Daniel F. Savarese
31 ***/
32
33 public final class FromNetASCIIInputStream extends PushbackInputStream
34 {
35 static final boolean _noConversionRequired;
36 static final String _lineSeparator;
37 static final byte[] _lineSeparatorBytes;
38
39 static {
40 _lineSeparator = System.getProperty("line.separator");
41 _noConversionRequired = _lineSeparator.equals("\r\n");
42 _lineSeparatorBytes = _lineSeparator.getBytes();
43 }
44
45 private int __length = 0;
46
47 /***
48 * Returns true if the NetASCII line separator differs from the system
49 * line separator, false if they are the same. This method is useful
50 * to determine whether or not you need to instantiate a
51 * FromNetASCIIInputStream object.
52 * <p>
53 * @return True if the NETASCII line separator differs from the local
54 * system line separator, false if they are the same.
55 ***/
56 public static final boolean isConversionRequired()
57 {
58 return !_noConversionRequired;
59 }
60
61 /***
62 * Creates a FromNetASCIIInputStream instance that wraps an existing
63 * InputStream.
64 ***/
65 public FromNetASCIIInputStream(InputStream input)
66 {
67 super(input, _lineSeparatorBytes.length + 1);
68 }
69
70
71 private int __read() throws IOException
72 {
73 int ch;
74
75 ch = super.read();
76
77 if (ch == '\r')
78 {
79 ch = super.read();
80 if (ch == '\n')
81 {
82 unread(_lineSeparatorBytes);
83 ch = super.read();
84
85 --__length;
86 }
87 else
88 {
89 if (ch != -1)
90 unread(ch);
91 return '\r';
92 }
93 }
94
95 return ch;
96 }
97
98
99 /***
100 * Reads and returns the next byte in the stream. If the end of the
101 * message has been reached, returns -1. Note that a call to this method
102 * may result in multiple reads from the underlying input stream in order
103 * to convert NETASCII line separators to the local line separator format.
104 * This is transparent to the programmer and is only mentioned for
105 * completeness.
106 * <p>
107 * @return The next character in the stream. Returns -1 if the end of the
108 * stream has been reached.
109 * @exception IOException If an error occurs while reading the underlying
110 * stream.
111 ***/
112 public int read() throws IOException
113 {
114 if (_noConversionRequired)
115 return super.read();
116
117 return __read();
118 }
119
120
121 /***
122 * Reads the next number of bytes from the stream into an array and
123 * returns the number of bytes read. Returns -1 if the end of the
124 * stream has been reached.
125 * <p>
126 * @param buffer The byte array in which to store the data.
127 * @return The number of bytes read. Returns -1 if the
128 * end of the message has been reached.
129 * @exception IOException If an error occurs in reading the underlying
130 * stream.
131 ***/
132 public int read(byte buffer[]) throws IOException
133 {
134 return read(buffer, 0, buffer.length);
135 }
136
137
138 /***
139 * Reads the next number of bytes from the stream into an array and returns
140 * the number of bytes read. Returns -1 if the end of the
141 * message has been reached. The characters are stored in the array
142 * starting from the given offset and up to the length specified.
143 * <p>
144 * @param buffer The byte array in which to store the data.
145 * @param offset The offset into the array at which to start storing data.
146 * @param length The number of bytes to read.
147 * @return The number of bytes read. Returns -1 if the
148 * end of the stream has been reached.
149 * @exception IOException If an error occurs while reading the underlying
150 * stream.
151 ***/
152 public int read(byte buffer[], int offset, int length) throws IOException
153 {
154 int ch, off;
155
156 if (length < 1)
157 return 0;
158
159 ch = available();
160
161 __length = (length > ch ? ch : length);
162
163
164 if (__length < 1)
165 __length = 1;
166
167 if (_noConversionRequired)
168 return super.read(buffer, offset, __length);
169
170 if ((ch = __read()) == -1)
171 return -1;
172
173 off = offset;
174
175 do
176 {
177 buffer[offset++] = (byte)ch;
178 }
179 while (--__length > 0 && (ch = __read()) != -1);
180
181
182 return (offset - off);
183 }
184
185
186
187 /***
188 * Returns the number of bytes that can be read without blocking EXCEPT
189 * when newline conversions have to be made somewhere within the
190 * available block of bytes. In other words, you really should not
191 * rely on the value returned by this method if you are trying to avoid
192 * blocking.
193 ***/
194 public int available() throws IOException
195 {
196 return (buf.length - pos) + in.available();
197 }
198
199 }