edu.mines.jtk.io.ArrayOutputAdapter Maven / Gradle / Ivy
/****************************************************************************
Copyright 2006, Colorado School of Mines and others.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
****************************************************************************/
package edu.mines.jtk.io;
import java.io.*;
import static java.lang.Math.min;
import java.nio.*;
import java.nio.channels.WritableByteChannel;
/**
* Implements {@link ArrayOutput} by wrapping {@link java.io.DataOutput}.
* This adapter wraps a specified data output to provide methods for writing
* values and arrays of values with an optionally specified byte order.
*
* Byte order should rarely be specified. Most applications should simply
* use the default BIG_ENDIAN byte order.
*
* When an adapter is constructed from an object that has a file channel,
* the channel enables more efficient writes of arrays of values.
* @author Dave Hale, Colorado School of Mines
* @version 2006.08.05
*/
public class ArrayOutputAdapter implements ArrayOutput {
/**
* Constructs an adapter for the specified data output.
* The default byte order is BIG_ENDIAN.
* @param output the data output.
*/
public ArrayOutputAdapter(DataOutput output) {
this(output,ByteOrder.BIG_ENDIAN);
}
/**
* Constructs an adapter for the specified random-access file.
* The file channel of the random-access file enables more efficient writes.
* @param file the random-access file.
*/
public ArrayOutputAdapter(RandomAccessFile file) {
this(file,ByteOrder.BIG_ENDIAN);
}
/**
* Constructs an adapter for the specified file output stream and byte order.
* The file channel of the file output stream enables more efficient writes.
* @param stream the file output stream.
*/
public ArrayOutputAdapter(FileOutputStream stream) {
this(stream,ByteOrder.BIG_ENDIAN);
}
/**
* Constructs an adapter for the specified data output and byte order.
* @param output the data output.
* @param order the byte order.
*/
public ArrayOutputAdapter(DataOutput output, ByteOrder order) {
this(null,output,order);
}
/**
* Constructs an adapter for the specified random-access file and byte order.
* The file channel of the random-access file enables more efficient writes.
* @param file the random-access file.
* @param order the byte order.
*/
public ArrayOutputAdapter(RandomAccessFile file, ByteOrder order) {
this(file.getChannel(),file,order);
}
/**
* Constructs an adapter for the specified file output stream and byte order.
* The file channel of the file output stream enables more efficient writes.
* @param stream the file output stream.
* @param order the byte order.
*/
public ArrayOutputAdapter(FileOutputStream stream, ByteOrder order) {
this(stream.getChannel(),new DataOutputStream(stream),order);
}
/**
* Constructs an adapter for the specified channel, output, and byte order.
* If not null, the writable byte channel enables more efficient writes.
* @param channel the writable byte channel; null, if none.
* @param output the data output.
* @param order the byte order.
*/
public ArrayOutputAdapter(
WritableByteChannel channel, DataOutput output, ByteOrder order)
{
_wbc = channel;
_do = output;
_bo = order;
if (_wbc!=null) {
_bb = ByteBuffer.allocateDirect(4096);
} else {
_buffer = new byte[4096];
_bb = ByteBuffer.wrap(_buffer);
}
if (order==ByteOrder.BIG_ENDIAN) {
_bb.order(ByteOrder.BIG_ENDIAN);
} else {
_bb.order(ByteOrder.LITTLE_ENDIAN);
}
_cb = _bb.asCharBuffer();
_sb = _bb.asShortBuffer();
_ib = _bb.asIntBuffer();
_lb = _bb.asLongBuffer();
_fb = _bb.asFloatBuffer();
_db = _bb.asDoubleBuffer();
}
/**
* Gets the byte order for this adapter.
* @return the byte order.
*/
public ByteOrder getByteOrder() {
return _bo;
}
// From DataOutput.
public void write(int b) throws IOException {
_do.write(b);
}
public void write(byte[] b) throws IOException {
_do.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
_do.write(b,off,len);
}
public void writeBoolean(boolean v) throws IOException {
_do.writeBoolean(v);
}
public void writeByte(int v) throws IOException {
_do.writeByte(v);
}
public void writeShort(int v) throws IOException {
if (_bo==ByteOrder.BIG_ENDIAN) {
_do.write((v>>>8)&0xFF);
_do.write((v )&0xFF);
} else {
_do.write((v )&0xFF);
_do.write((v>>>8)&0xFF);
}
}
public void writeChar(int v) throws IOException {
_do.writeShort(v);
}
public void writeInt(int v) throws IOException {
if (_bo==ByteOrder.BIG_ENDIAN) {
_do.write((v>>>24)&0xFF);
_do.write((v>>>16)&0xFF);
_do.write((v>>> 8)&0xFF);
_do.write((v )&0xFF);
} else {
_do.write((v )&0xFF);
_do.write((v>>> 8)&0xFF);
_do.write((v>>>16)&0xFF);
_do.write((v>>>24)&0xFF);
}
}
public void writeLong(long v) throws IOException {
if (_bo==ByteOrder.BIG_ENDIAN) {
_do.write((int)(v>>>56)&0xFF);
_do.write((int)(v>>>48)&0xFF);
_do.write((int)(v>>>40)&0xFF);
_do.write((int)(v>>>32)&0xFF);
_do.write((int)(v>>>24)&0xFF);
_do.write((int)(v>>>16)&0xFF);
_do.write((int)(v>>> 8)&0xFF);
_do.write((int)(v )&0xFF);
} else {
_do.write((int)(v )&0xFF);
_do.write((int)(v>>> 8)&0xFF);
_do.write((int)(v>>>16)&0xFF);
_do.write((int)(v>>>24)&0xFF);
_do.write((int)(v>>>32)&0xFF);
_do.write((int)(v>>>40)&0xFF);
_do.write((int)(v>>>48)&0xFF);
_do.write((int)(v>>>56)&0xFF);
}
}
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
public void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
public void writeBytes(String s) throws IOException {
_do.writeBytes(s);
}
public void writeChars(String s) throws IOException {
int n = s.length();
for (int i=0; i