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