    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      @Override public void write(byte[] b, int off, int len) throws IOException {
    056        // Override slow FilterOutputStream impl
    057        out.write(b, off, len);
    058      }
    059
    060      @Override public void writeBoolean(boolean v) throws IOException {
    061        ((DataOutputStream) out).writeBoolean(v);
    062      }
    063
    064      @Override public void writeByte(int v) throws IOException {
    065        ((DataOutputStream) out).writeByte(v);
    066      }
    067
    068      /**
    069       * @deprecated The semantics of {@code writeBytes(String s)} are considered
    070       *             dangerous. Please use {@link #writeUTF(String s)},
    071       *             {@link #writeChars(String s)} or another write method instead.
    072       */
    073      @Deprecated
    074      @Override public void writeBytes(String s) throws IOException {
    075        ((DataOutputStream) out).writeBytes(s);
    076      }
    077
    078      /**
    079       * Writes a char as specified by {@link DataOutputStream#writeChar(int)},
    080       * except using little-endian byte order.
    081       *
    082       * @throws IOException if an I/O error occurs
    083       */
    084      @Override public void writeChar(int v) throws IOException {
    085        writeShort(v);
    086      }
    087
    088      /**
    089       * Writes a {@code String} as specified by
    090       * {@link DataOutputStream#writeChars(String)}, except each character is
    091       * written using little-endian byte order.
    092       *
    093       * @throws IOException if an I/O error occurs
    094       */
    095      @Override public void writeChars(String s) throws IOException {
    096        for (int i = 0; i < s.length(); i++) {
    097          writeChar(s.charAt(i));
    098        }
    099      }
    100
    101      /**
    102       * Writes a {@code double} as specified by
    103       * {@link DataOutputStream#writeDouble(double)}, except using little-endian
    104       * byte order.
    105       *
    106       * @throws IOException if an I/O error occurs
    107       */
    108      @Override public void writeDouble(double v) throws IOException {
    109        writeLong(Double.doubleToLongBits(v));
    110      }
    111
    112      /**
    113       * Writes a {@code float} as specified by
    114       * {@link DataOutputStream#writeFloat(float)}, except using little-endian byte
    115       * order.
    116       *
    117       * @throws IOException if an I/O error occurs
    118       */
    119      @Override public void writeFloat(float v) throws IOException {
    120        writeInt(Float.floatToIntBits(v));
    121      }
    122
    123      /**
    124       * Writes an {@code int} as specified by
    125       * {@link DataOutputStream#writeInt(int)}, except using little-endian byte
    126       * order.
    127       *
    128       * @throws IOException if an I/O error occurs
    129       */
    130      @Override public void writeInt(int v) throws IOException {
    131        out.write(0xFF & v);
    132        out.write(0xFF & (v >> 8));
    133        out.write(0xFF & (v >> 16));
    134        out.write(0xFF & (v >> 24));
    135      }
    136
    137      /**
    138       * Writes a {@code long} as specified by
    139       * {@link DataOutputStream#writeLong(long)}, except using little-endian byte
    140       * order.
    141       *
    142       * @throws IOException if an I/O error occurs
    143       */
    144      @Override public void writeLong(long v) throws IOException {
    145        byte[] bytes = Longs.toByteArray(Long.reverseBytes(v));
    146        write(bytes, 0, bytes.length);
    147      }
    148
    149      /**
    150       * Writes a {@code short} as specified by
    151       * {@link DataOutputStream#writeShort(int)}, except using little-endian byte
    152       * order.
    153       *
    154       * @throws IOException if an I/O error occurs
    155       */
    156      @Override public void writeShort(int v) throws IOException {
    157        out.write(0xFF & v);
    158        out.write(0xFF & (v >> 8));
    159      }
    160
    161      @Override public void writeUTF(String str) throws IOException {
    162        ((DataOutputStream) out).writeUTF(str);
    163      }
    164    }