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.FilterInputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21
22 /***
23 * This class wraps an input stream, replacing all singly occurring
24 * <LF> (linefeed) characters with <CR><LF> (carriage return
25 * followed by linefeed), which is the NETASCII standard for representing
26 * a newline.
27 * You would use this class to implement ASCII file transfers requiring
28 * conversion to NETASCII.
29 * <p>
30 * <p>
31 * @author Daniel F. Savarese
32 ***/
33
34 public final class ToNetASCIIInputStream extends FilterInputStream
35 {
36 private static final int __NOTHING_SPECIAL = 0;
37 private static final int __LAST_WAS_CR = 1;
38 private static final int __LAST_WAS_NL = 2;
39 private int __status;
40
41 /***
42 * Creates a ToNetASCIIInputStream instance that wraps an existing
43 * InputStream.
44 * <p>
45 * @param input The InputStream to .
46 ***/
47 public ToNetASCIIInputStream(InputStream input)
48 {
49 super(input);
50 __status = __NOTHING_SPECIAL;
51 }
52
53
54 /***
55 * Reads and returns the next byte in the stream. If the end of the
56 * message has been reached, returns -1.
57 * <p>
58 * @return The next character in the stream. Returns -1 if the end of the
59 * stream has been reached.
60 * @exception IOException If an error occurs while reading the underlying
61 * stream.
62 ***/
63 public int read() throws IOException
64 {
65 int ch;
66
67 if (__status == __LAST_WAS_NL)
68 {
69 __status = __NOTHING_SPECIAL;
70 return '\n';
71 }
72
73 ch = in.read();
74
75 switch (ch)
76 {
77 case '\r':
78 __status = __LAST_WAS_CR;
79 return '\r';
80 case '\n':
81 if (__status != __LAST_WAS_CR)
82 {
83 __status = __LAST_WAS_NL;
84 return '\r';
85 }
86
87 default:
88 __status = __NOTHING_SPECIAL;
89 return ch;
90 }
91
92
93 }
94
95
96 /***
97 * Reads the next number of bytes from the stream into an array and
98 * returns the number of bytes read. Returns -1 if the end of the
99 * stream has been reached.
100 * <p>
101 * @param buffer The byte array in which to store the data.
102 * @return The number of bytes read. Returns -1 if the
103 * end of the message has been reached.
104 * @exception IOException If an error occurs in reading the underlying
105 * stream.
106 ***/
107 public int read(byte buffer[]) throws IOException
108 {
109 return read(buffer, 0, buffer.length);
110 }
111
112
113 /***
114 * Reads the next number of bytes from the stream into an array and returns
115 * the number of bytes read. Returns -1 if the end of the
116 * message has been reached. The characters are stored in the array
117 * starting from the given offset and up to the length specified.
118 * <p>
119 * @param buffer The byte array in which to store the data.
120 * @param offset The offset into the array at which to start storing data.
121 * @param length The number of bytes to read.
122 * @return The number of bytes read. Returns -1 if the
123 * end of the stream has been reached.
124 * @exception IOException If an error occurs while reading the underlying
125 * stream.
126 ***/
127 public int read(byte buffer[], int offset, int length) throws IOException
128 {
129 int ch, off;
130
131 if (length < 1)
132 return 0;
133
134 ch = available();
135
136 if (length > ch)
137 length = ch;
138
139
140 if (length < 1)
141 length = 1;
142
143 if ((ch = read()) == -1)
144 return -1;
145
146 off = offset;
147
148 do
149 {
150 buffer[offset++] = (byte)ch;
151 }
152 while (--length > 0 && (ch = read()) != -1);
153
154 return (offset - off);
155 }
156
157 /*** Returns false. Mark is not supported. ***/
158 public boolean markSupported()
159 {
160 return false;
161 }
162
163 public int available() throws IOException
164 {
165 int result;
166
167 result = in.available();
168
169 if (__status == __LAST_WAS_NL)
170 return (result + 1);
171
172 return result;
173 }
174 }