KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > nio > channels > Channels


1 /*
2  * @(#)Channels.java 1.23 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.nio.channels;
9
10 import java.io.FileInputStream JavaDoc;
11 import java.io.FileOutputStream JavaDoc;
12 import java.io.InputStream JavaDoc;
13 import java.io.OutputStream JavaDoc;
14 import java.io.Reader JavaDoc;
15 import java.io.Writer JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.nio.ByteBuffer JavaDoc;
18 import java.nio.CharBuffer JavaDoc;
19 import java.nio.BufferOverflowException JavaDoc;
20 import java.nio.BufferUnderflowException JavaDoc;
21 import java.nio.charset.Charset JavaDoc;
22 import java.nio.charset.CharsetDecoder JavaDoc;
23 import java.nio.charset.CharsetEncoder JavaDoc;
24 import java.nio.charset.CoderResult JavaDoc;
25 import java.nio.charset.UnsupportedCharsetException JavaDoc;
26 import java.nio.channels.spi.AbstractInterruptibleChannel JavaDoc;
27 import sun.nio.ch.ChannelInputStream;
28 import sun.nio.cs.StreamDecoder;
29 import sun.nio.cs.StreamEncoder;
30
31
32 /**
33  * Utility methods for channels and streams.
34  *
35  * <p> This class defines static methods that support the interoperation of the
36  * stream classes of the <tt>{@link java.io}</tt> package with the channel
37  * classes of this package. </p>
38  *
39  *
40  * @author Mark Reinhold
41  * @author Mike McCloskey
42  * @author JSR-51 Expert Group
43  * @version 1.23, 03/12/19
44  * @since 1.4
45  */

46
47 public final class Channels {
48
49     private Channels() { } // No instantiation
50

51
52     private static int write(WritableByteChannel JavaDoc ch, ByteBuffer JavaDoc bb)
53     throws IOException JavaDoc
54     {
55     if (ch instanceof SelectableChannel JavaDoc) {
56         SelectableChannel JavaDoc sc = (SelectableChannel JavaDoc)ch;
57         synchronized (sc.blockingLock()) {
58         if (!sc.isBlocking())
59             throw new IllegalBlockingModeException JavaDoc();
60         return ch.write(bb);
61         }
62     } else {
63         return ch.write(bb);
64     }
65     }
66
67
68     // -- Byte streams from channels --
69

70     /**
71      * Constructs a stream that reads bytes from the given channel.
72      *
73      * <p> The <tt>read</tt> methods of the resulting stream will throw an
74      * {@link IllegalBlockingModeException} if invoked while the underlying
75      * channel is in non-blocking mode. The stream will not be buffered, and
76      * it will not support the {@link InputStream#mark mark} or {@link
77      * InputStream#reset reset} methods. The stream will be safe for access by
78      * multiple concurrent threads. Closing the stream will in turn cause the
79      * channel to be closed. </p>
80      *
81      * @param ch
82      * The channel from which bytes will be read
83      *
84      * @return A new input stream
85      */

86     public static InputStream JavaDoc newInputStream(ReadableByteChannel JavaDoc ch) {
87     return new sun.nio.ch.ChannelInputStream(ch);
88     }
89
90     /**
91      * Constructs a stream that writes bytes to the given channel.
92      *
93      * <p> The <tt>write</tt> methods of the resulting stream will throw an
94      * {@link IllegalBlockingModeException} if invoked while the underlying
95      * channel is in non-blocking mode. The stream will not be buffered. The
96      * stream will be safe for access by multiple concurrent threads. Closing
97      * the stream will in turn cause the channel to be closed. </p>
98      *
99      * @param ch
100      * The channel to which bytes will be written
101      *
102      * @return A new output stream
103      */

104     public static OutputStream JavaDoc newOutputStream(final WritableByteChannel JavaDoc ch) {
105     return new OutputStream JavaDoc() {
106
107         private ByteBuffer JavaDoc bb = null;
108         private byte[] bs = null; // Invoker's previous array
109
private byte[] b1 = null;
110
111                 public synchronized void write(int b) throws IOException JavaDoc {
112                    if (b1 == null)
113                         b1 = new byte[1];
114                     b1[0] = (byte)b;
115                     this.write(b1);
116                 }
117
118                 public synchronized void write(byte[] bs, int off, int len)
119                     throws IOException JavaDoc
120                 {
121                     if ((off < 0) || (off > bs.length) || (len < 0) ||
122                         ((off + len) > bs.length) || ((off + len) < 0)) {
123                         throw new IndexOutOfBoundsException JavaDoc();
124                     } else if (len == 0) {
125                         return;
126                     }
127                     ByteBuffer JavaDoc bb = ((this.bs == bs)
128                                      ? this.bb
129                                      : ByteBuffer.wrap(bs));
130                     bb.limit(Math.min(off + len, bb.capacity()));
131                     bb.position(off);
132                     this.bb = bb;
133                     this.bs = bs;
134                     Channels.write(ch, bb);
135                 }
136
137         public void close() throws IOException JavaDoc {
138             ch.close();
139         }
140
141         };
142     }
143
144
145     // -- Channels from streams --
146

147     /**
148      * Constructs a channel that reads bytes from the given stream.
149      *
150      * <p> The resulting channel will not be buffered; it will simply redirect
151      * its I/O operations to the given stream. Closing the channel will in
152      * turn cause the stream to be closed. </p>
153      *
154      * @param in
155      * The stream from which bytes are to be read
156      *
157      * @return A new readable byte channel
158      */

159     public static ReadableByteChannel JavaDoc newChannel(final InputStream JavaDoc in) {
160         if (in instanceof FileInputStream JavaDoc) {
161             String JavaDoc inClass = in.getClass().toString();
162             if (inClass.equals("java.io.FileInputStream"))
163                return ((FileInputStream JavaDoc)in).getChannel();
164         }
165     return new ReadableByteChannelImpl(in);
166     }
167
168     private static class ReadableByteChannelImpl
169         extends AbstractInterruptibleChannel JavaDoc // Not really interruptible
170
implements ReadableByteChannel JavaDoc
171     {
172         InputStream JavaDoc in;
173         private static final int TRANSFER_SIZE = 8192;
174         private byte buf[] = new byte[0];
175         private boolean open = true;
176         private Object JavaDoc readLock = new Object JavaDoc();
177
178         ReadableByteChannelImpl(InputStream JavaDoc in) {
179             this.in = in;
180         }
181
182         public int read(ByteBuffer JavaDoc dst) throws IOException JavaDoc {
183             int len = dst.remaining();
184             int totalRead = 0;
185             int bytesRead = 0;
186             synchronized (readLock) {
187                 while (totalRead < len) {
188                     int bytesToRead = Math.min((len - totalRead),
189                                                TRANSFER_SIZE);
190                     if (buf.length < bytesToRead)
191                         buf = new byte[bytesToRead];
192                     if ((totalRead > 0) && !(in.available() > 0))
193                         break; // block at most once
194
try {
195                         begin();
196                         bytesRead = in.read(buf, 0, bytesToRead);
197                     } finally {
198                         end(bytesRead > 0);
199                     }
200                     if (bytesRead < 0)
201                         break;
202                     else
203                         totalRead += bytesRead;
204                     dst.put(buf, 0, bytesRead);
205                 }
206                 if ((bytesRead < 0) && (totalRead == 0))
207                     return -1;
208
209                 return totalRead;
210             }
211         }
212
213         protected void implCloseChannel() throws IOException JavaDoc {
214             in.close();
215             open = false;
216         }
217     }
218
219
220     /**
221      * Constructs a channel that writes bytes to the given stream.
222      *
223      * <p> The resulting channel will not be buffered; it will simply redirect
224      * its I/O operations to the given stream. Closing the channel will in
225      * turn cause the stream to be closed. </p>
226      *
227      * @param out
228      * The stream to which bytes are to be written
229      *
230      * @return A new writable byte channel
231      */

232     public static WritableByteChannel JavaDoc newChannel(final OutputStream JavaDoc out) {
233         if (out instanceof FileOutputStream JavaDoc) {
234             String JavaDoc outClass = out.getClass().toString();
235             if (outClass.equals("java.io.FileOutputStream"))
236                 return ((FileOutputStream JavaDoc)out).getChannel();
237         }
238     return new WritableByteChannelImpl(out);
239     }
240
241     private static class WritableByteChannelImpl
242         extends AbstractInterruptibleChannel JavaDoc // Not really interruptible
243
implements WritableByteChannel JavaDoc
244     {
245         OutputStream JavaDoc out;
246         private static final int TRANSFER_SIZE = 8192;
247         private byte buf[] = new byte[0];
248         private boolean open = true;
249         private Object JavaDoc writeLock = new Object JavaDoc();
250
251         WritableByteChannelImpl(OutputStream JavaDoc out) {
252             this.out = out;
253         }
254
255         public int write(ByteBuffer JavaDoc src) throws IOException JavaDoc {
256             int len = src.remaining();
257             int totalWritten = 0;
258             synchronized (writeLock) {
259                 while (totalWritten < len) {
260                     int bytesToWrite = Math.min((len - totalWritten),
261                                                 TRANSFER_SIZE);
262                     if (buf.length < bytesToWrite)
263                         buf = new byte[bytesToWrite];
264                     src.get(buf, 0, bytesToWrite);
265                     try {
266                         begin();
267                         out.write(buf, 0, bytesToWrite);
268                     } finally {
269                         end(bytesToWrite > 0);
270                     }
271             totalWritten += bytesToWrite;
272                 }
273                 return totalWritten;
274             }
275         }
276
277         protected void implCloseChannel() throws IOException JavaDoc {
278             out.close();
279             open = false;
280         }
281     }
282
283
284     // -- Character streams from channels --
285

286     /**
287      * Constructs a reader that decodes bytes from the given channel using the
288      * given decoder.
289      *
290      * <p> The resulting stream will contain an internal input buffer of at
291      * least <tt>minBufferCap</tt> bytes. The stream's <tt>read</tt> methods
292      * will, as needed, fill the buffer by reading bytes from the underlying
293      * channel; if the channel is in non-blocking mode when bytes are to be
294      * read then an {@link IllegalBlockingModeException} will be thrown. The
295      * resulting stream will not otherwise be buffered, and it will not support
296      * the {@link Reader#mark mark} or {@link Reader#reset reset} methods.
297      * Closing the stream will in turn cause the channel to be closed. </p>
298      *
299      * @param ch
300      * The channel from which bytes will be read
301      *
302      * @param dec
303      * The charset decoder to be used
304      *
305      * @param minBufferCap
306      * The minimum capacity of the internal byte buffer,
307      * or <tt>-1</tt> if an implementation-dependent
308      * default capacity is to be used
309      *
310      * @return A new reader
311      */

312     public static Reader JavaDoc newReader(ReadableByteChannel JavaDoc ch,
313                    CharsetDecoder JavaDoc dec,
314                    int minBufferCap)
315     {
316     dec.reset();
317     return StreamDecoder.forDecoder(ch, dec, minBufferCap);
318     }
319
320     /**
321      * Constructs a reader that decodes bytes from the given channel according
322      * to the named charset.
323      *
324      * <p> An invocation of this method of the form
325      *
326      * <blockquote><pre>
327      * Channels.newReader(ch, csname)</pre></blockquote>
328      *
329      * behaves in exactly the same way as the expression
330      *
331      * <blockquote><pre>
332      * Channels.newReader(ch,
333      * Charset.forName(csName)
334      * .newDecoder(),
335      * -1);</pre></blockquote>
336      *
337      * @param ch
338      * The channel from which bytes will be read
339      *
340      * @param csName
341      * The name of the charset to be used
342      *
343      * @return A new reader
344      *
345      * @throws UnsupportedCharsetException
346      * If no support for the named charset is available
347      * in this instance of the Java virtual machine
348      */

349     public static Reader JavaDoc newReader(ReadableByteChannel JavaDoc ch,
350                    String JavaDoc csName)
351     {
352     return newReader(ch, Charset.forName(csName).newDecoder(), -1);
353     }
354
355     /**
356      * Constructs a writer that encodes characters using the given encoder and
357      * writes the resulting bytes to the given channel.
358      *
359      * <p> The resulting stream will contain an internal output buffer of at
360      * least <tt>minBufferCap</tt> bytes. The stream's <tt>write</tt> methods
361      * will, as needed, flush the buffer by writing bytes to the underlying
362      * channel; if the channel is in non-blocking mode when bytes are to be
363      * written then an {@link IllegalBlockingModeException} will be thrown.
364      * The resulting stream will not otherwise be buffered. Closing the stream
365      * will in turn cause the channel to be closed. </p>
366      *
367      * @param ch
368      * The channel to which bytes will be written
369      *
370      * @param enc
371      * The charset encoder to be used
372      *
373      * @param minBufferCap
374      * The minimum capacity of the internal byte buffer,
375      * or <tt>-1</tt> if an implementation-dependent
376      * default capacity is to be used
377      *
378      * @return A new writer
379      */

380     public static Writer JavaDoc newWriter(final WritableByteChannel JavaDoc ch,
381                    final CharsetEncoder JavaDoc enc,
382                    final int minBufferCap)
383     {
384         enc.reset();
385     return StreamEncoder.forEncoder(ch, enc, minBufferCap);
386     }
387
388     /**
389      * Constructs a writer that encodes characters according to the named
390      * charset and writes the resulting bytes to the given channel.
391      *
392      * <p> An invocation of this method of the form
393      *
394      * <blockquote><pre>
395      * Channels.newWriter(ch, csname)</pre></blockquote>
396      *
397      * behaves in exactly the same way as the expression
398      *
399      * <blockquote><pre>
400      * Channels.newWriter(ch,
401      * Charset.forName(csName)
402      * .newEncoder(),
403      * -1);</pre></blockquote>
404      *
405      * @param ch
406      * The channel to which bytes will be written
407      *
408      * @param csName
409      * The name of the charset to be used
410      *
411      * @return A new writer
412      *
413      * @throws UnsupportedCharsetException
414      * If no support for the named charset is available
415      * in this instance of the Java virtual machine
416      */

417     public static Writer JavaDoc newWriter(WritableByteChannel JavaDoc ch,
418                    String JavaDoc csName)
419     {
420     return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
421     }
422
423 }
424
Popular Tags