001    /*
002     * Copyright (C) 2007 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.io;
018    
019    import com.google.common.annotations.Beta;
020    import com.google.common.base.Preconditions;
021    import com.google.common.primitives.Longs;
022    
023    import java.io.DataOutput;
024    import java.io.DataOutputStream;
025    import java.io.FilterOutputStream;
026    import java.io.IOException;
027    import java.io.OutputStream;
028    
029    /**
030     * An implementation of {@link DataOutput} that uses little-endian byte ordering
031     * for writing {@code char}, {@code short}, {@code int}, {@code float}, {@code
032     * double}, and {@code long} values.
033     * <p>
034     * <b>Note:</b> This class intentionally violates the specification of its
035     * supertype {@code DataOutput}, which explicitly requires big-endian byte
036     * order.
037     *
038     * @author Chris Nokleberg
039     * @author Keith Bottner
040     * @since 8.0
041     */
042    @Beta
043    public class LittleEndianDataOutputStream extends FilterOutputStream
044        implements DataOutput {
045    
046      /**
047       * Creates a {@code LittleEndianDataOutputStream} that wraps the given stream.
048       *
049       * @param out the stream to delegate to
050       */
051      public LittleEndianDataOutputStream(OutputStream out) {
052        super(new DataOutputStream(Preconditions.checkNotNull(out)));
053      }
054    
055      
056      @Override
057      public void write(byte[] b, int off, int len) throws IOException {
058        // Override slow FilterOutputStream impl
059        out.write(b, off, len);
060      }
061    
062      public void writeBoolean(boolean v) throws IOException {
063        ((DataOutputStream) out).writeBoolean(v);
064      }
065    
066      public void writeByte(int v) throws IOException {
067        ((DataOutputStream) out).writeByte(v);
068      }
069    
070      /**
071       * @deprecated The semantics of {@code writeBytes(String s)} are considered
072       *             dangerous. Please use {@link #writeUTF(String s)},
073       *             {@link #writeChars(String s)} or another write method instead.
074       */
075      @Deprecated
076      public void writeBytes(String s) throws IOException {
077        ((DataOutputStream) out).writeBytes(s);
078      }
079    
080      /**
081       * Writes a char as specified by {@link DataOutputStream#writeChar(int)},
082       * except using little-endian byte order.
083       *
084       * @throws IOException if an I/O error occurs
085       */
086      public void writeChar(int v) throws IOException {
087        writeShort(v);
088      }
089    
090      /**
091       * Writes a {@code String} as specified by
092       * {@link DataOutputStream#writeChars(String)}, except each character is
093       * written using little-endian byte order.
094       *
095       * @throws IOException if an I/O error occurs
096       */
097      public void writeChars(String s) throws IOException {
098        for (int i = 0; i < s.length(); i++) {
099          writeChar(s.charAt(i));
100        }
101      }
102    
103      /**
104       * Writes a {@code double} as specified by
105       * {@link DataOutputStream#writeDouble(double)}, except using little-endian
106       * byte order.
107       *
108       * @throws IOException if an I/O error occurs
109       */
110      public void writeDouble(double v) throws IOException {
111        writeLong(Double.doubleToLongBits(v));
112      }
113    
114      /**
115       * Writes a {@code float} as specified by
116       * {@link DataOutputStream#writeFloat(float)}, except using little-endian byte
117       * order.
118       *
119       * @throws IOException if an I/O error occurs
120       */
121      public void writeFloat(float v) throws IOException {
122        writeInt(Float.floatToIntBits(v));
123      }
124    
125      /**
126       * Writes an {@code int} as specified by
127       * {@link DataOutputStream#writeInt(int)}, except using little-endian byte
128       * order.
129       *
130       * @throws IOException if an I/O error occurs
131       */
132      public void writeInt(int v) throws IOException {
133        out.write(0xFF & v);
134        out.write(0xFF & (v >> 8));
135        out.write(0xFF & (v >> 16));
136        out.write(0xFF & (v >> 24));
137      }
138    
139      /**
140       * Writes a {@code long} as specified by
141       * {@link DataOutputStream#writeLong(long)}, except using little-endian byte
142       * order.
143       *
144       * @throws IOException if an I/O error occurs
145       */
146      public void writeLong(long v) throws IOException {
147        byte[] bytes = Longs.toByteArray(Long.reverseBytes(v));
148        write(bytes, 0, bytes.length);
149      }
150    
151      /**
152       * Writes a {@code short} as specified by
153       * {@link DataOutputStream#writeShort(int)}, except using little-endian byte
154       * order.
155       *
156       * @throws IOException if an I/O error occurs
157       */
158      public void writeShort(int v) throws IOException {
159        out.write(0xFF & v);
160        out.write(0xFF & (v >> 8));
161      }
162    
163      public void writeUTF(String str) throws IOException {
164        ((DataOutputStream) out).writeUTF(str);
165      }
166    }