blob: f40bb3de06b2d6d6a09152daae9bd89734c30732 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.iotdb.tsfile.utils;
import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import org.apache.iotdb.tsfile.read.reader.TsFileInput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.BINARY;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.BOOLEAN;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.DOUBLE;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.FLOAT;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.INTEGER;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.LONG;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.NULL;
import static org.apache.iotdb.tsfile.utils.ReadWriteIOUtils.ClassSerializeId.STRING;
/**
* ConverterUtils is a utility class. It provides conversion between normal datatype and byte array.
*/
public class ReadWriteIOUtils {
public static final int BOOLEAN_LEN = 1;
public static final int SHORT_LEN = 2;
public static final int INT_LEN = 4;
public static final int LONG_LEN = 8;
public static final int DOUBLE_LEN = 8;
public static final int FLOAT_LEN = 4;
public static final float BIT_LEN = 0.125F;
private static final int NO_BYTE_TO_READ = -1;
private static final byte[] magicStringBytes;
private static final String RETURN_ERROR = "Intend to read %d bytes but %d are actually returned";
static {
magicStringBytes = BytesUtils.stringToBytes(TSFileConfig.MAGIC_STRING);
}
private ReadWriteIOUtils() {}
/** read a bool from inputStream. */
public static boolean readBool(InputStream inputStream) throws IOException {
int flag = inputStream.read();
return flag == 1;
}
// used by generated code
@SuppressWarnings("unused")
public static boolean readBoolean(InputStream inputStream) throws IOException {
int flag = inputStream.read();
return flag == 1;
}
/** read a bool from byteBuffer. */
public static boolean readBool(ByteBuffer buffer) {
byte a = buffer.get();
return a == 1;
}
/** read a Boolean from byteBuffer. */
public static Boolean readBoolObject(ByteBuffer buffer) {
byte a = buffer.get();
if (a == 1) {
return true;
} else if (a == 0) {
return false;
}
return null;
}
/** Read a Boolean from byteBuffer. */
public static Boolean readBoolObject(InputStream inputStream) throws IOException {
int flag = inputStream.read();
if (flag == 1) {
return true;
} else if (flag == 0) {
return false;
}
return null;
}
/** Read a byte from byteBuffer. */
public static byte readByte(ByteBuffer buffer) {
return buffer.get();
}
/**
* Read bytes array in given size
*
* @param buffer buffer
* @param size size
* @return bytes array
*/
public static byte[] readBytes(ByteBuffer buffer, int size) {
byte[] res = new byte[size];
buffer.get(res);
return res;
}
/** read a bool from byteBuffer. */
public static boolean readIsNull(InputStream inputStream) throws IOException {
return readBool(inputStream);
}
/** read a bool from byteBuffer. */
public static boolean readIsNull(ByteBuffer buffer) {
return readBool(buffer);
}
public static int write(Map<String, String> map, OutputStream stream) throws IOException {
if (map == null) {
return write(NO_BYTE_TO_READ, stream);
}
int length = 0;
length += write(map.size(), stream);
for (Entry<String, String> entry : map.entrySet()) {
length += write(entry.getKey(), stream);
length += write(entry.getValue(), stream);
}
return length;
}
public static void write(List<Map<String, String>> maps, OutputStream stream) throws IOException {
for (Map<String, String> map : maps) {
write(map, stream);
}
}
public static int write(Map<String, String> map, ByteBuffer buffer) {
if (map == null) {
return write(NO_BYTE_TO_READ, buffer);
}
int length = 0;
byte[] bytes;
buffer.putInt(map.size());
length += 4;
for (Entry<String, String> entry : map.entrySet()) {
if (entry.getKey() == null) {
buffer.putInt(-1);
} else {
bytes = entry.getKey().getBytes();
buffer.putInt(bytes.length);
buffer.put(bytes);
length += bytes.length;
}
length += 4;
if (entry.getValue() == null) {
buffer.putInt(-1);
} else {
bytes = entry.getValue().getBytes();
buffer.putInt(bytes.length);
buffer.put(bytes);
length += bytes.length;
}
length += 4;
}
return length;
}
public static void write(List<Map<String, String>> maps, ByteBuffer buffer) {
for (Map<String, String> map : maps) {
write(map, buffer);
}
}
/**
* write a int value to outputStream according to flag. If flag is true, write 1, else write 0.
*/
public static int write(Boolean flag, OutputStream outputStream) throws IOException {
if (flag == null) {
outputStream.write(-1);
} else if (Boolean.TRUE.equals(flag)) {
outputStream.write(1);
} else {
outputStream.write(0);
}
return BOOLEAN_LEN;
}
/** write a byte to byteBuffer according to flag. If flag is true, write 1, else write 0. */
public static int write(Boolean flag, ByteBuffer buffer) {
byte a;
if (flag == null) {
a = -1;
} else if (Boolean.TRUE.equals(flag)) {
a = 1;
} else {
a = 0;
}
buffer.put(a);
return BOOLEAN_LEN;
}
/**
* write a byte n.
*
* @return The number of bytes used to represent a {@code byte} value in two's complement binary
* form.
*/
public static int write(byte n, OutputStream outputStream) throws IOException {
outputStream.write(n);
return Byte.BYTES;
}
/**
* write a short n.
*
* @return The number of bytes used to represent n.
*/
public static int write(short n, OutputStream outputStream) throws IOException {
byte[] bytes = BytesUtils.shortToBytes(n);
outputStream.write(bytes);
return bytes.length;
}
/**
* write a byte n to byteBuffer.
*
* @return The number of bytes used to represent a {@code byte} value in two's complement binary
* form.
*/
public static int write(byte n, ByteBuffer buffer) {
buffer.put(n);
return Byte.BYTES;
}
/**
* write a short n to byteBuffer.
*
* @return The number of bytes used to represent n.
*/
public static int write(short n, ByteBuffer buffer) {
buffer.putShort(n);
return SHORT_LEN;
}
/**
* write a short n to byteBuffer.
*
* @return The number of bytes used to represent n.
*/
public static int write(Binary n, ByteBuffer buffer) {
buffer.putInt(n.getLength());
buffer.put(n.getValues());
return INT_LEN + n.getLength();
}
/**
* write a int n to outputStream.
*
* @return The number of bytes used to represent n.
*/
public static int write(int n, OutputStream outputStream) throws IOException {
byte[] bytes = BytesUtils.intToBytes(n);
outputStream.write(bytes);
return INT_LEN;
}
/** write the size (int) of the binary and then the bytes in binary */
public static int write(Binary binary, OutputStream outputStream) throws IOException {
byte[] size = BytesUtils.intToBytes(binary.getValues().length);
outputStream.write(size);
outputStream.write(binary.getValues());
return size.length + binary.getValues().length;
}
/**
* write a int n to byteBuffer.
*
* @return The number of bytes used to represent n.
*/
public static int write(int n, ByteBuffer buffer) {
buffer.putInt(n);
return INT_LEN;
}
/**
* Write a float n to outputStream.
*
* @return The number of bytes used to represent n.
*/
public static int write(float n, OutputStream outputStream) throws IOException {
byte[] bytes = BytesUtils.floatToBytes(n);
outputStream.write(bytes);
return FLOAT_LEN;
}
/**
* Write a double n to outputStream.
*
* @return The number of bytes used to represent n.
*/
public static int write(double n, OutputStream outputStream) throws IOException {
byte[] bytes = BytesUtils.doubleToBytes(n);
outputStream.write(bytes);
return DOUBLE_LEN;
}
/**
* write a long n to outputStream.
*
* @return The number of bytes used to represent n.
*/
public static int write(long n, OutputStream outputStream) throws IOException {
byte[] bytes = BytesUtils.longToBytes(n);
outputStream.write(bytes);
return LONG_LEN;
}
/** write a long n to byteBuffer. */
public static int write(long n, ByteBuffer buffer) {
buffer.putLong(n);
return LONG_LEN;
}
/** write a float n to byteBuffer. */
public static int write(float n, ByteBuffer buffer) {
buffer.putFloat(n);
return FLOAT_LEN;
}
/** write a double n to byteBuffer. */
public static int write(double n, ByteBuffer buffer) {
buffer.putDouble(n);
return DOUBLE_LEN;
}
/**
* Write string to outputStream.
*
* @return the length of string represented by byte[].
*/
public static int write(String s, OutputStream outputStream) throws IOException {
int len = 0;
if (s == null) {
len += write(NO_BYTE_TO_READ, outputStream);
return len;
}
byte[] bytes = s.getBytes();
len += write(bytes.length, outputStream);
outputStream.write(bytes);
len += bytes.length;
return len;
}
/**
* Write string to outputStream.
*
* @return the length of string represented by byte[].
*/
public static int writeVar(String s, OutputStream outputStream) throws IOException {
int len = 0;
if (s == null) {
len += ReadWriteForEncodingUtils.writeVarInt(NO_BYTE_TO_READ, outputStream);
return len;
}
byte[] bytes = s.getBytes(TSFileConfig.STRING_CHARSET);
len += ReadWriteForEncodingUtils.writeVarInt(bytes.length, outputStream);
outputStream.write(bytes);
len += bytes.length;
return len;
}
/**
* write string to byteBuffer.
*
* @return the length of string represented by byte[].
*/
public static int write(String s, ByteBuffer buffer) {
if (s == null) {
return write(NO_BYTE_TO_READ, buffer);
}
int len = 0;
byte[] bytes = s.getBytes();
len += write(bytes.length, buffer);
buffer.put(bytes);
len += bytes.length;
return len;
}
public static int writeVar(String s, ByteBuffer buffer) {
if (s == null) {
return ReadWriteForEncodingUtils.writeVarInt(NO_BYTE_TO_READ, buffer);
}
int len = 0;
byte[] bytes = s.getBytes();
len += ReadWriteForEncodingUtils.writeVarInt(bytes.length, buffer);
buffer.put(bytes);
len += bytes.length;
return len;
}
/** write byteBuffer.capacity and byteBuffer.array to outputStream. */
public static int write(ByteBuffer byteBuffer, OutputStream outputStream) throws IOException {
int len = 0;
len += write(byteBuffer.capacity(), outputStream);
byte[] bytes = byteBuffer.array();
outputStream.write(bytes);
len += bytes.length;
return len;
}
public static void writeWithoutSize(
ByteBuffer byteBuffer, int offset, int len, OutputStream outputStream) throws IOException {
byte[] bytes = byteBuffer.array();
outputStream.write(bytes, offset, len);
}
/** write byteBuffer.capacity and byteBuffer.array to byteBuffer. */
public static int write(ByteBuffer byteBuffer, ByteBuffer buffer) {
int len = 0;
len += write(byteBuffer.capacity(), buffer);
byte[] bytes = byteBuffer.array();
buffer.put(bytes);
len += bytes.length;
return len;
}
/** CompressionType. */
public static int write(CompressionType compressionType, OutputStream outputStream)
throws IOException {
byte n = compressionType.serialize();
return write(n, outputStream);
}
/** write compressionType to byteBuffer. */
public static int write(CompressionType compressionType, ByteBuffer buffer) {
byte n = compressionType.serialize();
return write(n, buffer);
}
/** TSDataType. */
public static int write(TSDataType dataType, OutputStream outputStream) throws IOException {
byte n = dataType.serialize();
return write(n, outputStream);
}
public static int write(TSDataType dataType, ByteBuffer buffer) {
byte n = dataType.serialize();
return write(n, buffer);
}
/** TSEncoding. */
public static int write(TSEncoding encoding, OutputStream outputStream) throws IOException {
byte n = encoding.serialize();
return write(n, outputStream);
}
public static int write(TSEncoding encoding, ByteBuffer buffer) {
byte n = encoding.serialize();
return write(n, buffer);
}
public static int sizeToWrite(Binary n) {
return INT_LEN + n.getLength();
}
public static int sizeToWrite(String s) {
if (s == null) {
return INT_LEN;
}
return INT_LEN + s.getBytes().length;
}
/** read a byte var from inputStream. */
public static byte readByte(InputStream inputStream) throws IOException {
return (byte) inputStream.read();
}
/** read a short var from inputStream. */
public static short readShort(InputStream inputStream) throws IOException {
byte[] bytes = new byte[SHORT_LEN];
int readLen = inputStream.read(bytes);
if (readLen != SHORT_LEN) {
throw new IOException(String.format(RETURN_ERROR, SHORT_LEN, readLen));
}
return BytesUtils.bytesToShort(bytes);
}
/** Read a short var from byteBuffer. */
public static short readShort(ByteBuffer buffer) {
return buffer.getShort();
}
/** Read a float var from inputStream. */
public static float readFloat(InputStream inputStream) throws IOException {
byte[] bytes = new byte[FLOAT_LEN];
int readLen = inputStream.read(bytes);
if (readLen != FLOAT_LEN) {
throw new IOException(String.format(RETURN_ERROR, FLOAT_LEN, readLen));
}
return BytesUtils.bytesToFloat(bytes);
}
/** Read a float var from byteBuffer. */
public static float readFloat(ByteBuffer byteBuffer) {
byte[] bytes = new byte[FLOAT_LEN];
byteBuffer.get(bytes);
return BytesUtils.bytesToFloat(bytes);
}
/** Read a double var from inputStream. */
public static double readDouble(InputStream inputStream) throws IOException {
byte[] bytes = new byte[DOUBLE_LEN];
int readLen = inputStream.read(bytes);
if (readLen != DOUBLE_LEN) {
throw new IOException(String.format(RETURN_ERROR, DOUBLE_LEN, readLen));
}
return BytesUtils.bytesToDouble(bytes);
}
/** Read a double var from byteBuffer. */
public static double readDouble(ByteBuffer byteBuffer) {
byte[] bytes = new byte[DOUBLE_LEN];
byteBuffer.get(bytes);
return BytesUtils.bytesToDouble(bytes);
}
/** Read an int var from inputStream. */
public static int readInt(InputStream inputStream) throws IOException {
byte[] bytes = new byte[INT_LEN];
int readLen = inputStream.read(bytes);
if (readLen != INT_LEN) {
throw new IOException(String.format(RETURN_ERROR, INT_LEN, readLen));
}
return BytesUtils.bytesToInt(bytes);
}
/** Read a int var from byteBuffer. */
public static int readInt(ByteBuffer buffer) {
return buffer.getInt();
}
/**
* Read an unsigned byte(0 ~ 255) as InputStream does.
*
* @return the byte or -1(means there is no byte to read)
*/
public static int read(ByteBuffer buffer) {
if (!buffer.hasRemaining()) {
return NO_BYTE_TO_READ;
}
return buffer.get() & 0xFF;
}
/** Read a long var from inputStream. */
public static long readLong(InputStream inputStream) throws IOException {
byte[] bytes = new byte[LONG_LEN];
int readLen = inputStream.read(bytes);
if (readLen != LONG_LEN) {
throw new IOException(String.format(RETURN_ERROR, LONG_LEN, readLen));
}
return BytesUtils.bytesToLong(bytes);
}
/** Read a long var from byteBuffer. */
public static long readLong(ByteBuffer buffer) {
return buffer.getLong();
}
/** Read string from inputStream. */
public static String readString(InputStream inputStream) throws IOException {
int strLength = readInt(inputStream);
if (strLength <= 0) {
return null;
}
byte[] bytes = new byte[strLength];
int readLen = inputStream.read(bytes, 0, strLength);
if (readLen != strLength) {
throw new IOException(String.format(RETURN_ERROR, strLength, readLen));
}
return new String(bytes, 0, strLength);
}
/** String length's type is varInt */
public static String readVarIntString(InputStream inputStream) throws IOException {
int strLength = ReadWriteForEncodingUtils.readVarInt(inputStream);
if (strLength < 0) {
return null;
} else if (strLength == 0) {
return "";
}
byte[] bytes = new byte[strLength];
int readLen = inputStream.read(bytes, 0, strLength);
if (readLen != strLength) {
throw new IOException(String.format(RETURN_ERROR, strLength, readLen));
}
return new String(bytes, 0, strLength);
}
/** Read string from byteBuffer. */
public static String readString(ByteBuffer buffer) {
int strLength = readInt(buffer);
if (strLength < 0) {
return null;
} else if (strLength == 0) {
return "";
}
byte[] bytes = new byte[strLength];
buffer.get(bytes, 0, strLength);
return new String(bytes, 0, strLength);
}
/** String length's type is varInt */
public static String readVarIntString(ByteBuffer buffer) {
int strLength = ReadWriteForEncodingUtils.readVarInt(buffer);
if (strLength < 0) {
return null;
} else if (strLength == 0) {
return "";
}
byte[] bytes = new byte[strLength];
buffer.get(bytes, 0, strLength);
return new String(bytes, 0, strLength);
}
/** Read string from byteBuffer with user define length. */
public static String readStringWithLength(ByteBuffer buffer, int length) {
if (length < 0) {
return null;
} else if (length == 0) {
return "";
}
byte[] bytes = new byte[length];
buffer.get(bytes, 0, length);
return new String(bytes, 0, length);
}
public static ByteBuffer getByteBuffer(String s) {
return ByteBuffer.wrap(s.getBytes(java.nio.charset.StandardCharsets.UTF_8));
}
public static ByteBuffer getByteBuffer(int i) {
return ByteBuffer.allocate(4).putInt(0, i);
}
public static ByteBuffer getByteBuffer(long n) {
return ByteBuffer.allocate(8).putLong(0, n);
}
public static ByteBuffer getByteBuffer(float f) {
return ByteBuffer.allocate(4).putFloat(0, f);
}
public static ByteBuffer getByteBuffer(double d) {
return ByteBuffer.allocate(8).putDouble(0, d);
}
public static ByteBuffer getByteBuffer(boolean i) {
return ByteBuffer.allocate(1).put(i ? (byte) 1 : (byte) 0);
}
public static String readStringFromDirectByteBuffer(ByteBuffer buffer)
throws CharacterCodingException {
return java.nio.charset.StandardCharsets.UTF_8
.newDecoder()
.decode(buffer.duplicate())
.toString();
}
/**
* unlike InputStream.read(bytes), this method makes sure that you can read length bytes or reach
* to the end of the stream.
*/
public static byte[] readBytes(InputStream inputStream, int length) throws IOException {
byte[] bytes = new byte[length];
int offset = 0;
int len;
while (bytes.length - offset > 0
&& (len = inputStream.read(bytes, offset, bytes.length - offset)) != NO_BYTE_TO_READ) {
offset += len;
}
return bytes;
}
public static Map<String, String> readMap(ByteBuffer buffer) {
int length = readInt(buffer);
if (length == NO_BYTE_TO_READ) {
return null;
}
Map<String, String> map = new HashMap<>(length);
for (int i = 0; i < length; i++) {
// key
String key = readString(buffer);
// value
String value = readString(buffer);
map.put(key, value);
}
return map;
}
public static Map<String, String> readMap(InputStream inputStream) throws IOException {
int length = readInt(inputStream);
if (length == NO_BYTE_TO_READ) {
return null;
}
Map<String, String> map = new HashMap<>(length);
for (int i = 0; i < length; i++) {
// key
String key = readString(inputStream);
// value
String value = readString(inputStream);
map.put(key, value);
}
return map;
}
public static LinkedHashMap<String, String> readLinkedHashMap(ByteBuffer buffer) {
int length = readInt(buffer);
if (length == NO_BYTE_TO_READ) {
return null;
}
LinkedHashMap<String, String> map = new LinkedHashMap<>(length);
for (int i = 0; i < length; i++) {
// key
String key = readString(buffer);
// value
String value = readString(buffer);
map.put(key, value);
}
return map;
}
public static List<Map<String, String>> readMaps(ByteBuffer buffer, int totalSize) {
List<Map<String, String>> results = new ArrayList<>(totalSize);
for (int i = 0; i < totalSize; i++) {
results.add(ReadWriteIOUtils.readMap(buffer));
}
return results;
}
/**
* unlike InputStream.read(bytes), this method makes sure that you can read length bytes or reach
* to the end of the stream.
*/
public static byte[] readBytesWithSelfDescriptionLength(InputStream inputStream)
throws IOException {
int length = readInt(inputStream);
return readBytes(inputStream, length);
}
public static Binary readBinary(ByteBuffer buffer) {
int length = readInt(buffer);
byte[] bytes = readBytes(buffer, length);
return new Binary(bytes);
}
public static Binary readBinary(InputStream inputStream) throws IOException {
int length = readInt(inputStream);
byte[] bytes = readBytes(inputStream, length);
return new Binary(bytes);
}
/**
* read bytes from byteBuffer, this method makes sure that you can read length bytes or reach to
* the end of the buffer.
*
* <p>read a int + buffer
*/
public static byte[] readByteBufferWithSelfDescriptionLength(ByteBuffer buffer) {
int byteLength = ReadWriteForEncodingUtils.readUnsignedVarInt(buffer);
byte[] bytes = new byte[byteLength];
buffer.get(bytes);
return bytes;
}
/** read bytes from buffer with offset position to the end of buffer. */
public static int readAsPossible(TsFileInput input, long position, ByteBuffer buffer)
throws IOException {
int length = 0;
int read;
while (buffer.hasRemaining() && (read = input.read(buffer, position)) != NO_BYTE_TO_READ) {
length += read;
position += read;
input.read(buffer, position);
}
return length;
}
/** read util to the end of buffer. */
public static int readAsPossible(TsFileInput input, ByteBuffer buffer) throws IOException {
int length = 0;
int read;
while (buffer.hasRemaining() && (read = input.read(buffer)) != NO_BYTE_TO_READ) {
length += read;
}
return length;
}
/** read bytes from buffer with offset position to the end of buffer or up to len. */
public static int readAsPossible(TsFileInput input, ByteBuffer target, long offset, int len)
throws IOException {
int length = 0;
int limit = target.limit();
if (target.remaining() > len) {
target.limit(target.position() + len);
}
int read;
while (length < len
&& target.hasRemaining()
&& (read = input.read(target, offset)) != NO_BYTE_TO_READ) {
length += read;
offset += read;
}
target.limit(limit);
return length;
}
/** read string list with self define length. */
public static List<String> readStringList(InputStream inputStream) throws IOException {
List<String> list = new ArrayList<>();
int size = readInt(inputStream);
for (int i = 0; i < size; i++) {
list.add(readString(inputStream));
}
return list;
}
/** read string list with self define length. */
public static List<String> readStringList(ByteBuffer buffer) {
int size = readInt(buffer);
if (size <= 0) {
return Collections.emptyList();
}
List<String> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
list.add(readString(buffer));
}
return list;
}
/** write string list with self define length. */
public static void writeStringList(List<String> list, ByteBuffer buffer) {
if (list == null) {
throw new IllegalArgumentException("stringList must not be null!");
}
int size = list.size();
buffer.putInt(size);
for (String s : list) {
write(s, buffer);
}
}
/** write string list with self define length. */
public static void writeStringList(List<String> list, OutputStream outputStream)
throws IOException {
if (list == null) {
throw new IllegalArgumentException("stringList must not be null!");
}
int size = list.size();
write(size, outputStream);
for (String s : list) {
write(s, outputStream);
}
}
/** read integer set with self define length. */
public static Set<Integer> readIntegerSet(ByteBuffer buffer) {
int size = readInt(buffer);
if (size <= 0) {
return Collections.emptySet();
}
Set<Integer> set = new HashSet<>();
for (int i = 0; i < size; i++) {
set.add(readInt(buffer));
}
return set;
}
private static final String SET_NOT_NULL_MSG = "set must not be null!";
// write integer set with self define length
public static void writeIntegerSet(Set<Integer> set, OutputStream outputStream)
throws IOException {
if (set == null) {
throw new IllegalArgumentException(SET_NOT_NULL_MSG);
}
int size = set.size();
write(size, outputStream);
for (int i : set) {
write(i, outputStream);
}
}
// Read long set with self define length
public static Set<Long> readLongSet(ByteBuffer buffer) {
int size = readInt(buffer);
if (size <= 0) {
return Collections.emptySet();
}
Set<Long> set = new HashSet<>();
for (int i = 0; i < size; i++) {
set.add(readLong(buffer));
}
return set;
}
// write long set with self define length
public static void writeLongSet(Set<Long> set, DataOutputStream outputStream) throws IOException {
if (set == null) {
throw new IllegalArgumentException(SET_NOT_NULL_MSG);
}
write(set.size(), outputStream);
for (long e : set) {
write(e, outputStream);
}
}
// read object set with self define length
public static <T> Set<T> readObjectSet(ByteBuffer buffer) {
int size = readInt(buffer);
if (size <= 0) {
return Collections.emptySet();
}
Set<T> set = new HashSet<>();
for (int i = 0; i < size; i++) {
set.add((T) readObject(buffer));
}
return set;
}
// write object set with self define length
public static <T> void writeObjectSet(Set<T> set, DataOutputStream outputStream)
throws IOException {
if (set == null) {
throw new IllegalArgumentException(SET_NOT_NULL_MSG);
}
write(set.size(), outputStream);
for (T e : set) {
writeObject(e, outputStream);
}
}
public static CompressionType readCompressionType(InputStream inputStream) throws IOException {
byte n = readByte(inputStream);
return CompressionType.deserialize(n);
}
public static CompressionType readCompressionType(ByteBuffer buffer) {
byte n = buffer.get();
return CompressionType.deserialize(n);
}
public static TSDataType readDataType(InputStream inputStream) throws IOException {
byte n = readByte(inputStream);
return TSDataType.deserialize(n);
}
public static TSDataType readDataType(ByteBuffer buffer) {
byte n = buffer.get();
return TSDataType.deserialize(n);
}
public static TSEncoding readEncoding(InputStream inputStream) throws IOException {
byte n = readByte(inputStream);
return TSEncoding.deserialize(n);
}
public static TSEncoding readEncoding(ByteBuffer buffer) {
byte n = buffer.get();
return TSEncoding.deserialize(n);
}
/**
* To check whether the byte buffer is reach the magic string this method doesn't change the
* position of the byte buffer
*
* @param byteBuffer byte buffer
* @return whether the byte buffer is reach the magic string
*/
public static boolean checkIfMagicString(ByteBuffer byteBuffer) {
byteBuffer.mark();
boolean res = Arrays.equals(readBytes(byteBuffer, magicStringBytes.length), magicStringBytes);
byteBuffer.reset();
return res;
}
/**
* to check whether the inputStream is reach the magic string this method doesn't change the
* position of the inputStream
*
* @param inputStream inputStream
* @return whether the inputStream is reach the magic string
*/
public static boolean checkIfMagicString(InputStream inputStream) throws IOException {
return inputStream.available() <= magicStringBytes.length;
}
enum ClassSerializeId {
LONG,
DOUBLE,
INTEGER,
FLOAT,
BINARY,
BOOLEAN,
STRING,
NULL
}
public static void writeObject(Object value, DataOutputStream outputStream) {
try {
if (value instanceof Long) {
outputStream.write(LONG.ordinal());
outputStream.writeLong((Long) value);
} else if (value instanceof Double) {
outputStream.write(DOUBLE.ordinal());
outputStream.writeDouble((Double) value);
} else if (value instanceof Integer) {
outputStream.write(INTEGER.ordinal());
outputStream.writeInt((Integer) value);
} else if (value instanceof Float) {
outputStream.write(FLOAT.ordinal());
outputStream.writeFloat((Float) value);
} else if (value instanceof Binary) {
outputStream.write(BINARY.ordinal());
byte[] bytes = ((Binary) value).getValues();
outputStream.writeInt(bytes.length);
outputStream.write(bytes);
} else if (value instanceof Boolean) {
outputStream.write(BOOLEAN.ordinal());
outputStream.write(Boolean.TRUE.equals(value) ? 1 : 0);
} else if (value == null) {
outputStream.write(NULL.ordinal());
} else {
outputStream.write(STRING.ordinal());
byte[] bytes = value.toString().getBytes();
outputStream.writeInt(bytes.length);
outputStream.write(bytes);
}
} catch (IOException ignored) {
// ignored
}
}
public static void writeObject(Object value, ByteBuffer byteBuffer) {
if (value instanceof Long) {
byteBuffer.putInt(LONG.ordinal());
byteBuffer.putLong((Long) value);
} else if (value instanceof Double) {
byteBuffer.putInt(DOUBLE.ordinal());
byteBuffer.putDouble((Double) value);
} else if (value instanceof Integer) {
byteBuffer.putInt(INTEGER.ordinal());
byteBuffer.putInt((Integer) value);
} else if (value instanceof Float) {
byteBuffer.putInt(FLOAT.ordinal());
byteBuffer.putFloat((Float) value);
} else if (value instanceof Binary) {
byteBuffer.putInt(BINARY.ordinal());
byte[] bytes = ((Binary) value).getValues();
byteBuffer.putInt(bytes.length);
byteBuffer.put(bytes);
} else if (value instanceof Boolean) {
byteBuffer.putInt(BOOLEAN.ordinal());
byteBuffer.put(Boolean.TRUE.equals(value) ? (byte) 1 : (byte) 0);
} else if (value == null) {
byteBuffer.putInt(NULL.ordinal());
} else {
byteBuffer.putInt(STRING.ordinal());
byte[] bytes = value.toString().getBytes();
byteBuffer.putInt(bytes.length);
byteBuffer.put(bytes);
}
}
public static Object readObject(ByteBuffer buffer) {
ClassSerializeId serializeId = ClassSerializeId.values()[buffer.get()];
switch (serializeId) {
case BOOLEAN:
return buffer.get() == 1;
case FLOAT:
return buffer.getFloat();
case DOUBLE:
return buffer.getDouble();
case LONG:
return buffer.getLong();
case INTEGER:
return buffer.getInt();
case BINARY:
int length = buffer.getInt();
byte[] bytes = new byte[length];
buffer.get(bytes);
return new Binary(bytes);
case NULL:
return null;
case STRING:
default:
length = buffer.getInt();
bytes = new byte[length];
buffer.get(bytes);
return new String(bytes);
}
}
public static ByteBuffer clone(ByteBuffer original) {
ByteBuffer clone = ByteBuffer.allocate(original.remaining());
while (original.hasRemaining()) {
clone.put(original.get());
}
clone.flip();
return clone;
}
/**
* The skip method of will return only if skipping n bytes or reaching end of file.
*
* @param inputStream the inputSteam to be skipped.
* @param n the number of bytes to be skipped.
* @throws IOException if the stream does not support seek, or if some other I/O error occurs.
*/
public static void skip(InputStream inputStream, long n) throws IOException {
while (n > 0) {
long skipN = inputStream.skip(n);
if (skipN > 0) {
n -= skipN;
} else {
// read one byte to decide should we retry
if (inputStream.read() == -1) {
// EOF
break;
} else {
n--;
}
}
}
}
}