package edu.stanford.nlp.util; import java.io.*; import java.util.Vector; /** * This is used to convert an array of double into byte array which makes it possible to keep it more efficiently. * * @author Kristina Toutanova */ public final class ConvertByteArray { private ConvertByteArray() {} // static methods private static short SHORTFLAG = 0x00ff; private static int INTFLAG = 0x000000ff; private static long LONGFLAG = 0x00000000000000ff; public static void writeIntToByteArr(byte[] b, int off, int i) { b[off] = (byte) i; b[off + 1] = (byte) (i >> 8); b[off + 2] = (byte) (i >> 16); b[off + 3] = (byte) (i >> 24); } public static void writeLongToByteArr(byte[] b, int off, long l) { for (int i = 0; i < 8; i++) { b[off + i] = (byte) (l >> (8 * i)); } } public static void writeFloatToByteArr(byte[] b, int off, float f) { int i = Float.floatToIntBits(f); writeIntToByteArr(b, off, i); } public static void writeDoubleToByteArr(byte[] b, int off, double d) { long l = Double.doubleToLongBits(d); writeLongToByteArr(b, off, l); } public static void writeBooleanToByteArr(byte[] b, int off, boolean bool) { if (bool) { b[off] = 0; } else { b[off] = 1; } } public static void writeCharToByteArr(byte[] b, int off, char c) { b[off + 1] = (byte) c; b[off] = (byte) (c >> 8); } public static void writeShortToByteArr(byte[] b, int off, short s) { b[off] = (byte) s; b[off + 1] = (byte) (s >> 8); } public static void writeUStringToByteArr(byte[] b, int off, String s) { for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); b[2 * i + 1 + off] = (byte) c; b[2 * i + off] = (byte) (c >> 8); } } public static void writeUStringToByteArr(byte[] b, int off, String s, int pos, int length) { for (int i = pos; i < (pos + length); i++) { char c = s.charAt(i); b[2 * i + 1 + off] = (byte) c; b[2 * i + off] = (byte) (c >> 8); } } public static void writeAStringToByteArr(byte[] b, int off, String s) { System.arraycopy(s.getBytes(), 0, b, off, s.length()); } public static void writeAStringToByteArr(byte[] b, int off, String s, int pos, int length) { String sub = s.substring(pos, pos + length); writeAStringToByteArr(b, off, sub); } //------------------------------------------------------------------- public static int byteArrToInt(byte[] b, int off) { int z = 0; for (int i = 3; i > 0; i--) { z = (z | (b[off + i] & INTFLAG)) << 8; } z = z | (b[off] & INTFLAG); return z; } public static short byteArrToShort(byte[] b, int off) { short s = (short) (((0 | (b[off + 1] & SHORTFLAG)) << 8) | (b[off] & SHORTFLAG)); return s; } public static float byteArrToFloat(byte[] b, int off) { int i = byteArrToInt(b, off); return Float.intBitsToFloat(i); } public static double byteArrToDouble(byte[] b, int off) { long l = byteArrToLong(b, off); return Double.longBitsToDouble(l); } public static long byteArrToLong(byte[] b, int off) { long z = 0; for (int i = 7; i > 0; i--) { z = (z | (b[off + i] & LONGFLAG)) << 8; } z = z | (b[off] & LONGFLAG); return z; } public static boolean byteArrToBoolean(byte[] b, int off) { return b[off] == 0; } public static char byteArrToChar(byte[] b, int off) { char c = (char) ((b[off] << 8) | b[off + 1]); return c; } public static String byteArrToUString(byte[] b) { String s; if (b.length == 0) { s = ""; } else { char[] c = new char[b.length / 2]; for (int i = 0; i < (b.length / 2); i++) { int j = (b[2 * i] << 8) | b[2 * i + 1]; c[i] = (char) j; } s = new String(c); } return s; } public static String byteArrToUString(byte[] b, int off, int strLen) { String s; if (strLen == 0) { s = ""; } else { char[] c = new char[strLen]; for (int i = 0; i < strLen; i++) { int j = (b[2 * i + off] << 8) | b[2 * i + 1 + off]; c[i] = (char) j; } s = new String(c); } return s; } public static String byteArrToAString(byte[] b) { return new String(b); } public static String byteArrToAString(byte[] b, int off, int length) { if (length == 0) { return ""; } else { return new String(b, off, length); } } //----------------------------------------------------------------- public static byte[] stringUToByteArr(String s) { char c; byte[] b = new byte[2 * s.length()]; for (int i = 0; i < s.length(); i++) { c = s.charAt(i); b[2 * i + 1] = (byte) c; b[2 * i] = (byte) (c >> 8); } return b; } public static byte[] stringAToByteArr(String s) { return s.getBytes(); } //----------------------------------------------------------------- public static byte[] intArrToByteArr(int[] i) { return intArrToByteArr(i, 0, i.length); } public static byte[] intArrToByteArr(int[] i, int off, int length) { byte[] y = new byte[4 * length]; for (int j = off; j < (off + length); j++) { y[4 * (j - off)] = (byte) i[j]; y[4 * (j - off) + 1] = (byte) (i[j] >> 8); y[4 * (j - off) + 2] = (byte) (i[j] >> 16); y[4 * (j - off) + 3] = (byte) (i[j] >> 24); } return y; } public static void intArrToByteArr(byte[] b, int pos, int[] i, int off, int len) { for (int j = off; j < (off + len); j++) { b[4 * (j - off) + pos] = (byte) i[j]; b[4 * (j - off) + 1 + pos] = (byte) (i[j] >> 8); b[4 * (j - off) + 2 + pos] = (byte) (i[j] >> 16); b[4 * (j - off) + 3 + pos] = (byte) (i[j] >> 24); } } public static byte[] longArrToByteArr(long[] l) { return longArrToByteArr(l, 0, l.length); } public static byte[] longArrToByteArr(long[] l, int off, int length) { byte[] b = new byte[8 * length]; for (int j = off; j < (off + length); j++) { for (int i = 0; i < 8; i++) { b[8 * (j - off) + i] = (byte) (l[j] >> (8 * i)); } } return b; } public static void longArrToByteArr(byte[] b, int pos, long[] l, int off, int length) { for (int j = off; j < (off + length); j++) { for (int i = 0; i < 8; i++) { b[8 * (j - off) + i + pos] = (byte) (l[j] >> (8 * i)); } } } public static byte[] booleanArrToByteArr(boolean[] b) { return booleanArrToByteArr(b, 0, b.length); } public static byte[] booleanArrToByteArr(boolean[] b, int off, int len) { byte[] bytes = new byte[len]; for (int i = 0; i < len; i++) { if (b[i]) { bytes[i] = 0; } else { bytes[i] = 1; } } return bytes; } public static void booleanArrToByteArr(byte[] bytes, int pos, boolean[] b, int off, int length) { for (int i = 0; i < length; i++) { if (b[i]) { bytes[i + pos] = 0; } else { bytes[i + pos] = 1; } } } public static byte[] charArrToByteArr(char[] c) { return charArrToByteArr(c, 0, c.length); } public static byte[] charArrToByteArr(char[] c, int off, int len) { byte[] b = new byte[len * 2]; for (int i = 0; i < len; i++) { b[2 * i + 1] = (byte) c[off + i]; b[2 * i] = (byte) (c[off + i] >> 8); } return b; } public static void charArrToByteArr(byte[] b, int pos, char[] c, int off, int len) { for (int i = 0; i < len; i++) { b[2 * i + 1 + pos] = (byte) c[off + i]; b[2 * i + pos] = (byte) (c[off + i] >> 8); } } public static byte[] floatArrToByteArr(float[] f) { return floatArrToByteArr(f, 0, f.length); } public static byte[] floatArrToByteArr(float[] f, int off, int length) { byte[] y = new byte[4 * length]; for (int j = off; j < (off + length); j++) { int i = Float.floatToIntBits(f[j]); y[4 * (j - off)] = (byte) i; y[4 * (j - off) + 1] = (byte) (i >> 8); y[4 * (j - off) + 2] = (byte) (i >> 16); y[4 * (j - off) + 3] = (byte) (i >> 24); } return y; } public static void floatArrToByteArr(byte[] b, int pos, float[] f, int off, int len) { for (int j = off; j < (off + len); j++) { int i = Float.floatToIntBits(f[j]); b[4 * (j - off) + pos] = (byte) i; b[4 * (j - off) + 1 + pos] = (byte) (i >> 8); b[4 * (j - off) + 2 + pos] = (byte) (i >> 16); b[4 * (j - off) + 3 + pos] = (byte) (i >> 24); } } public static byte[] doubleArrToByteArr(double[] d) { return doubleArrToByteArr(d, 0, d.length); } public static byte[] doubleArrToByteArr(double[] d, int off, int length) { byte[] b = new byte[8 * length]; for (int j = off; j < (off + length); j++) { long l = Double.doubleToLongBits(d[j]); for (int i = 0; i < 8; i++) { b[8 * (j - off) + i] = (byte) (l >> (8 * i)); } } return b; } public static void doubleArrToByteArr(byte[] b, int pos, double[] d, int off, int length) { for (int j = off; j < (off + length); j++) { long l = Double.doubleToLongBits(d[j]); for (int i = 0; i < 8; i++) { b[8 * (j - off) + i + pos] = (byte) (l >> (8 * i)); } } } public static byte[] shortArrToByteArr(short[] s) { return shortArrToByteArr(s, 0, s.length); } public static byte[] shortArrToByteArr(short[] s, int off, int length) { byte[] y = new byte[2 * length]; for (int j = off; j < (off + length); j++) { y[4 * (j - off)] = (byte) s[j]; y[4 * (j - off) + 1] = (byte) (s[j] >> 8); } return y; } public static void shortArrToByteArr(byte[] b, int pos, short[] s, int off, int len) { for (int j = off; j < (off + len); j++) { b[4 * (j - off) + pos] = (byte) s[j]; b[4 * (j - off) + 1 + pos] = (byte) (s[j] >> 8); } } public static byte[] uStringArrToByteArr(String[] s) { return uStringArrToByteArr(s, 0, s.length); } public static byte[] uStringArrToByteArr(String[] s, int off, int length) { int byteOff = 0; int byteCount = 0; for (int i = off; i < (off + length); i++) { if (s[i] != null) { byteCount += 2 * s[i].length(); } } byte[] b = new byte[byteCount + 4 * s.length]; for (int i = off; i < (off + length); i++) { if (s[i] != null) { writeIntToByteArr(b, byteOff, s[i].length()); byteOff += 4; writeUStringToByteArr(b, byteOff, s[i]); byteOff += 2 * s[i].length(); } else { writeIntToByteArr(b, byteOff, 0); byteOff += 4; } } return b; } public static void uStringArrToByteArr(byte[] b, int pos, String[] s, int off, int length) { for (int i = off; i < (off + length); i++) { if (s[i] != null) { writeIntToByteArr(b, pos, s[i].length()); pos += 4; writeUStringToByteArr(b, pos, s[i]); pos += 2 * s[i].length(); } else { writeIntToByteArr(b, pos, 0); pos += 4; } } } public static byte[] aStringArrToByteArr(String[] s) { return aStringArrToByteArr(s, 0, s.length); } public static byte[] aStringArrToByteArr(String[] s, int off, int length) { int byteOff = 0; int byteCount = 0; for (int i = off; i < (off + length); i++) { if (s[i] != null) { byteCount += s[i].length(); } } byte[] b = new byte[byteCount + 4 * s.length]; for (int i = off; i < (off + length); i++) { if (s[i] != null) { writeIntToByteArr(b, byteOff, s[i].length()); byteOff += 4; writeAStringToByteArr(b, byteOff, s[i]); byteOff += s[i].length(); } else { writeIntToByteArr(b, byteOff, 0); byteOff += 4; } } return b; } public static void aStringArrToByteArr(byte[] b, int pos, String[] s, int off, int length) { for (int i = off; i < (off + length); i++) { if (s[i] != null) { writeIntToByteArr(b, pos, s[i].length()); pos += 4; writeAStringToByteArr(b, pos, s[i]); pos += s[i].length(); } else { writeIntToByteArr(b, pos, 0); pos += 4; } } } //----------------------------------------------------------------- public static int[] byteArrToIntArr(byte[] b) { return byteArrToIntArr(b, 0, b.length / 4); } public static int[] byteArrToIntArr(byte[] b, int off, int length) { int[] z = new int[length]; for (int i = 0; i < length; i++) { z[i] = 0; for (int j = 3; j > 0; j--) { z[i] = (z[i] | (b[off + j + 4 * i] & INTFLAG)) << 8; } z[i] = z[i] | (b[off + 4 * i] & INTFLAG); } return z; } public static void byteArrToIntArr(byte[] b, int off, int[] i, int pos, int length) { for (int j = 0; j < length; j++) { i[j + pos] = 0; for (int k = 3; k > 0; k--) { i[j + pos] = (i[j + pos] | (b[off + k + 4 * j] & INTFLAG)) << 8; } i[j + pos] = i[j + pos] | (b[off + 4 * j] & INTFLAG); } } public static long[] byteArrToLongArr(byte[] b) { return byteArrToLongArr(b, 0, b.length / 8); } public static long[] byteArrToLongArr(byte[] b, int off, int length) { long[] l = new long[length]; for (int i = 0; i < length; i++) { l[i] = 0; for (int j = 0; j < 8; j++) { l[i] = l[i] | ((b[8 * i + j + off] & 0x000000ff) << (8 * j)); } } return l; } public static void byteArrToLongArr(byte[] b, int off, long[] l, int pos, int length) { for (int i = 0; i < length; i++) { l[i + pos] = 0; for (int j = 0; j < 8; j++) { l[i + pos] = l[i + pos] | ((b[8 * i + j + off] & 0x000000ff) << (8 * j)); } } } public static boolean[] byteArrToBooleanArr(byte[] b) { return byteArrToBooleanArr(b, 0, b.length); } public static boolean[] byteArrToBooleanArr(byte[] b, int off, int length) { boolean[] bool = new boolean[length]; for (int i = 0; i < length; i++) { bool[i] = b[i + off] == 0; } return bool; } public static void byteArrToBooleanArr(byte[] b, int off, boolean[] bool, int pos, int length) { for (int i = 0; i < length; i++) { bool[i + pos] = b[i + off] == 0; } } public static char[] byteArrToCharArr(byte[] b) { return byteArrToCharArr(b, 0, b.length / 2); } public static char[] byteArrToCharArr(byte[] b, int off, int length) { char[] c = new char[length]; for (int i = 0; i < (length); i++) { c[i] = (char) ((b[2 * i + off] << 8) | b[2 * i + 1 + off]); } return c; } public static void byteArrToCharArr(byte[] b, int off, char[] c, int pos, int length) { for (int i = 0; i < (length); i++) { c[i + pos] = (char) ((b[2 * i + off] << 8) | b[2 * i + 1 + off]); } } public static short[] byteArrToShortArr(byte[] b) { return byteArrToShortArr(b, 0, b.length / 2); } public static short[] byteArrToShortArr(byte[] b, int off, int length) { short[] z = new short[length]; for (int i = 0; i < length; i++) { z[i] = (short) (((0 | (b[off + 1 + 2 * i] & SHORTFLAG)) << 8) | (b[off + 2 * i] & SHORTFLAG)); } return z; } public static void byteArrToShortArr(byte[] b, int off, short[] s, int pos, int length) { for (int i = 0; i < length; i++) { s[i + pos] = (short) (((0 | (b[off + 1 + 2 * i] & SHORTFLAG)) << 8) | (b[off + 2 * i] & SHORTFLAG)); } } public static float[] byteArrToFloatArr(byte[] b) { return byteArrToFloatArr(b, 0, b.length / 4); } public static float[] byteArrToFloatArr(byte[] b, int off, int length) { float[] z = new float[length]; for (int i = 0; i < length; i++) { int k = 0; for (int j = 3; j > 0; j--) { k = (k | (b[off + j + 4 * i] & INTFLAG)) << 8; } k = k | (b[off + 4 * i] & INTFLAG); z[i] = Float.intBitsToFloat(k); } return z; } public static void byteArrToFloatArr(byte[] b, int off, float[] f, int pos, int length) { for (int i = 0; i < length; i++) { int k = 0; for (int j = 3; j > 0; j--) { k = (k | (b[off + j + 4 * i] & INTFLAG)) << 8; } k = k | (b[off + 4 * i] & INTFLAG); f[pos + i] = Float.intBitsToFloat(k); } } /** This method allocates a new double[] to return, based on the size of * the array b (namely b.length / 8 in size) * @param b Array to decode to doubles * @return Array of doubles. */ public static double[] byteArrToDoubleArr(byte[] b) { return byteArrToDoubleArr(b, 0, b.length / 8); } public static double[] byteArrToDoubleArr(byte[] b, int off, int length) { double[] d = new double[length]; for (int i = 0; i < length; i++) { long l = 0; for (int j = 0; j < 8; j++) { l = l | ((long) (b[8 * i + j + off] & 0x00000000000000ff) << (8 * j)); } d[i] = Double.longBitsToDouble(l); } return d; } public static void byteArrToDoubleArr(byte[] b, int off, double[] d, int pos, int length) { for (int i = 0; i < length; i++) { long l = 0; for (int j = 0; j < 8; j++) { l = l | ((long) (b[8 * i + j + off] & 0x00000000000000ff) << (8 * j)); } d[pos + i] = Double.longBitsToDouble(l); } } public static String[] byteArrToUStringArr(byte[] b) { int off = 0; Vector<String> v = new Vector<>(); while (off < b.length) { int length = byteArrToInt(b, off); if (length != 0) { v.addElement(byteArrToUString(b, off + 4, length)); } else { v.addElement(""); } off = off + 2 * length + 4; } String[] s = new String[v.size()]; for (int i = 0; i < s.length; i++) { s[i] = v.elementAt(i); } return s; } public static String[] byteArrToUStringArr(byte[] b, int off, int length) { String[] s = new String[length]; for (int i = 0; i < length; i++) { int stringLen = byteArrToInt(b, off); off += 4; if (stringLen != 0) { s[i] = byteArrToUString(b, off, stringLen); off += 2 * s[i].length(); } else { s[i] = ""; } } return s; } public static void byteArrToUStringArr(byte[] b, int off, String[] s, int pos, int length) { for (int i = 0; i < length; i++) { int stringLen = byteArrToInt(b, off); off += 4; if (stringLen != 0) { s[i + pos] = byteArrToUString(b, off, stringLen); off += 2 * s[i].length(); } else { s[i] = ""; } } } public static String[] byteArrToAStringArr(byte[] b) { int off = 0; Vector<String> v = new Vector<>(); while (off < b.length) { int length = byteArrToInt(b, off); if (length != 0) { v.addElement(byteArrToAString(b, off + 4, length)); } else { v.addElement(""); } off = off + length + 4; } String[] s = new String[v.size()]; for (int i = 0; i < s.length; i++) { s[i] = v.elementAt(i); } return s; } public static String[] byteArrToAStringArr(byte[] b, int off, int length) { String[] s = new String[length]; for (int i = 0; i < length; i++) { int stringLen = byteArrToInt(b, off); off += 4; if (stringLen != 0) { s[i] = byteArrToAString(b, off, stringLen); off += s[i].length(); } else { s[i] = ""; } } return s; } public static void byteArrToAStringArr(byte[] b, int off, String[] s, int pos, int length) { for (int i = 0; i < length; i++) { int stringLen = byteArrToInt(b, off); off += 4; if (stringLen != 0) { s[i + pos] = byteArrToAString(b, off, stringLen); off += s[i].length(); } else { s[i] = ""; } } } public static void saveDoubleArr(DataOutputStream rf, double[] arr) throws IOException { rf.writeInt(arr.length); byte[] lArr = doubleArrToByteArr(arr); rf.write(lArr); rf.close(); } public static void saveFloatArr(DataOutputStream rf, float[] arr) throws IOException { rf.writeInt(arr.length); byte[] lArr = floatArrToByteArr(arr); rf.write(lArr); rf.close(); } public static double[] readDoubleArr(DataInputStream rf) throws IOException { int size = rf.readInt(); byte[] b = new byte[8 * size]; rf.read(b); return byteArrToDoubleArr(b); } public static float[] readFloatArr(DataInputStream rf) throws IOException { int size = rf.readInt(); byte[] b = new byte[4 * size]; rf.read(b); return byteArrToFloatArr(b); } }