host.anzo.commons.io.binary.FileBinaryWriter Maven / Gradle / Ivy
package host.anzo.commons.io.binary;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.util.Arrays;
/**
* @author ANZO
*/
@Slf4j
public class FileBinaryWriter implements AutoCloseable {
@Getter
private ByteBuffer byteBuffer;
private FileChannel roChannel = null;
@SuppressWarnings("unused")
public FileBinaryWriter(int capacity) {
this(ByteBuffer.allocate(capacity));
}
@SuppressWarnings("unused")
public FileBinaryWriter(ByteBuffer byteBuffer) {
this.byteBuffer = byteBuffer;
this.byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
@SuppressWarnings({"unused", "resource"})
public FileBinaryWriter(@NotNull Path path) throws IOException {
this.roChannel = new RandomAccessFile(path.toFile(), "r").getChannel();
this.byteBuffer = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, roChannel.size()).load();
this.byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
}
@SuppressWarnings("unused")
private FileBinaryWriter(byte[] byteBuffer) {
this(ByteBuffer.wrap(byteBuffer));
}
public void writeC(int data) {
byteBuffer.put((byte) data);
}
public void writeCB(boolean value) {
byteBuffer.put(value ? (byte) 1 : (byte) 0);
}
public void writeF(float value) {
byteBuffer.putFloat(value);
}
public void writeFF(double value) {
byteBuffer.putDouble(value);
}
public void writeH(int value) {
byteBuffer.putShort((short) value);
}
public void writeD(int value) {
byteBuffer.putInt(value);
}
public void writeD(long value) {
byteBuffer.putInt((int)(value & 0xFFFFFFFF));
}
public void writeQ(long value) {
byteBuffer.putLong(value);
}
public void writeB(byte[] data) {
byteBuffer.put(data);
}
public void writeB(byte data) {
byteBuffer.put(data);
}
public void writeS(CharSequence charSequence) {
if (charSequence != null) {
int length = charSequence.length();
for (int i = 0; i < length; i++) {
byteBuffer.putChar(charSequence.charAt(i));
}
}
byteBuffer.putChar('\000');
}
public final void writeS(CharSequence charSequence, int size) {
if (charSequence == null) {
byteBuffer.put(new byte[size]);
}
else {
final int startPosition = byteBuffer.position();
for (int i = 0; i < charSequence.length(); i++) {
if ((byteBuffer.position() - startPosition) < size) {
byteBuffer.putChar(charSequence.charAt(i));
}
}
final int length = byteBuffer.position() - startPosition;
if (length < size) {
writeB(new byte[size - length]);
}
}
}
public void writeQS(@NotNull CharSequence charSequence) {
int length = charSequence.length();
writeQ(length);
for (int i = 0; i < length; i++) {
byteBuffer.putChar(charSequence.charAt(i));
}
}
public void write(@NotNull Field field, Object object) throws IllegalAccessException {
switch (field.getType().getTypeName()) {
case "java.lang.Byte":
case "byte":
case "java.lang.Boolean":
case "boolean":
writeB(field.getByte(object));
break;
case "int":
case "java.lang.Integer":
writeD(field.getInt(object));
break;
case "java.lang.Short":
case "short":
writeH(field.getShort(object));
break;
case "java.lang.Long":
case "long":
writeQ(field.getLong(object));
break;
case "java.lang.Float":
case "float":
writeF(field.getFloat(object));
break;
case "java.lang.Double":
case "double":
writeFF(field.getDouble(object));
default:
log.error("Unsupported class [{}]", field.getType().getTypeName());
break;
}
}
public void setPosition(int position) {
byteBuffer.position(position);
}
public int getPosition() {
return byteBuffer.position();
}
public String getPositionHex() {
return Integer.toHexString(getPosition());
}
public int getAvailableBytes() {
return byteBuffer.remaining();
}
public void trim() {
final int dataEndPosition = getPosition();
byteBuffer = ByteBuffer.wrap(byteBuffer.array(), 0, dataEndPosition);
}
public byte[] toByteArray() {
return Arrays.copyOfRange(byteBuffer.array(), 0, getPosition());
}
public void writeToFile(Path path) {
try (FileOutputStream outputStream = new FileOutputStream(path.toFile(), false);
FileChannel channel = outputStream.getChannel()) {
trim();
channel.write(byteBuffer);
}
catch (Exception e) {
log.error("Error while writing buffer to file [{}]", path.toString(), e);
}
}
@Override
public void close() throws IOException {
if (roChannel != null) {
try {
roChannel.close();
}
catch (IOException e) {
log.error("Error while closing FileBinaryWriter channel!", e);
}
}
if (byteBuffer != null) {
try {
byteBuffer.clear();
}
catch (Exception e) {
log.error("Error while closing FileBinaryWriter buffer!", e);
}
}
}
}