View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.buffer;
17  
18  import io.netty.util.CharsetUtil;
19  import io.netty.util.internal.ObjectUtil;
20  
21  import java.io.DataOutput;
22  import java.io.DataOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStream;
25  
26  /**
27   * An {@link OutputStream} which writes data to a {@link ByteBuf}.
28   * <p>
29   * A write operation against this stream will occur at the {@code writerIndex}
30   * of its underlying buffer and the {@code writerIndex} will increase during
31   * the write operation.
32   * <p>
33   * This stream implements {@link DataOutput} for your convenience.
34   * The endianness of the stream is not always big endian but depends on
35   * the endianness of the underlying buffer.
36   *
37   * @see ByteBufInputStream
38   */
39  public class ByteBufOutputStream extends OutputStream implements DataOutput {
40  
41      private final ByteBuf buffer;
42      private final int startIndex;
43      private DataOutputStream utf8out; // lazily-instantiated
44      private boolean closed;
45  
46      /**
47       * Creates a new stream which writes data to the specified {@code buffer}.
48       */
49      public ByteBufOutputStream(ByteBuf buffer) {
50          this.buffer = ObjectUtil.checkNotNull(buffer, "buffer");
51          startIndex = buffer.writerIndex();
52      }
53  
54      /**
55       * Returns the number of written bytes by this stream so far.
56       */
57      public int writtenBytes() {
58          return buffer.writerIndex() - startIndex;
59      }
60  
61      @Override
62      public void write(byte[] b, int off, int len) throws IOException {
63          if (len == 0) {
64              return;
65          }
66  
67          buffer.writeBytes(b, off, len);
68      }
69  
70      @Override
71      public void write(byte[] b) throws IOException {
72          buffer.writeBytes(b);
73      }
74  
75      @Override
76      public void write(int b) throws IOException {
77          buffer.writeByte(b);
78      }
79  
80      @Override
81      public void writeBoolean(boolean v) throws IOException {
82          buffer.writeBoolean(v);
83      }
84  
85      @Override
86      public void writeByte(int v) throws IOException {
87          buffer.writeByte(v);
88      }
89  
90      @Override
91      public void writeBytes(String s) throws IOException {
92          buffer.writeCharSequence(s, CharsetUtil.US_ASCII);
93      }
94  
95      @Override
96      public void writeChar(int v) throws IOException {
97          buffer.writeChar(v);
98      }
99  
100     @Override
101     public void writeChars(String s) throws IOException {
102         int len = s.length();
103         for (int i = 0 ; i < len ; i ++) {
104             buffer.writeChar(s.charAt(i));
105         }
106     }
107 
108     @Override
109     public void writeDouble(double v) throws IOException {
110         buffer.writeDouble(v);
111     }
112 
113     @Override
114     public void writeFloat(float v) throws IOException {
115         buffer.writeFloat(v);
116     }
117 
118     @Override
119     public void writeInt(int v) throws IOException {
120         buffer.writeInt(v);
121     }
122 
123     @Override
124     public void writeLong(long v) throws IOException {
125         buffer.writeLong(v);
126     }
127 
128     @Override
129     public void writeShort(int v) throws IOException {
130         buffer.writeShort((short) v);
131     }
132 
133     @Override
134     public void writeUTF(String s) throws IOException {
135         DataOutputStream out = utf8out;
136         if (out == null) {
137             if (closed) {
138                 throw new IOException("The stream is closed");
139             }
140             // Suppress a warning since the stream is closed in the close() method
141             utf8out = out = new DataOutputStream(this); // lgtm[java/output-resource-leak]
142         }
143         out.writeUTF(s);
144     }
145 
146     /**
147      * Returns the buffer where this stream is writing data.
148      */
149     public ByteBuf buffer() {
150         return buffer;
151     }
152 
153     @Override
154     public void close() throws IOException {
155         if (closed) {
156             return;
157         }
158         closed = true;
159 
160         try {
161             super.close();
162         } finally {
163             if (utf8out != null) {
164                 utf8out.close();
165             }
166         }
167     }
168 }