将long转换为" byte-array-ed"文本,没有堆分配

时间:2014-07-27 18:07:45

标签: java arrays string garbage-collection long-integer

我想在Java中以文本形式将(正)原始long转换为byte[]

例如,简单的方法是:123 => "123" => [49, 50, 51]

然而,将long转换为String堆 - 分配String,我试图避免这个用于我的无GC库。我宁愿直接在预先分配的字节数组上渲染它。

因此,我的问题是如何直接从long转换为byte[]表示,如果我使用String构造函数调用(对于上面的示例),则给出“123”。为了澄清,我不打算将long编码为二进制形式的byte[],而是文本形式。

谢谢! Ñ

5 个答案:

答案 0 :(得分:4)

这个简单的程序:

long l = 123;
int size = (int)(Math.log10(l)+1);
byte[] array = new byte[size];
for (int i = 0; i < size; i++) {
    long temp = (long) Math.pow(10, size - i - 1);
    array[i] = (byte) ((l / temp) + 48);
    l = l % temp;
}
System.out.println(Arrays.toString(array)); // [49, 50, 51]

我已经以毫秒为单位对当前时间进行了测试并按预期工作:

long l = System.currentTimeMillis();
...
System.out.println(Arrays.toString(array));

输出:

1406485727149
[49, 52, 48, 54, 52, 56, 53, 55, 50, 55, 49, 52, 57]

答案 1 :(得分:3)

要编写它而不使用byte []或使用相当昂贵的Math.pow和Math.log,您可以执行以下操作。

public static void toStream(OutputStream os, long l) throws IOException {
    toStream0(os, l / 10);
    os.write((int) ('0' + l % 10));
}

private static void toStream0(OutputStream os, long l) throws IOException {
    if (l == 0) return;
    toStream0(os, l / 10);
    os.write((int) ('0' + l % 10));
}

toStream(System.out, System.currentTimeMillis());

打印

1406486588664

如果您正在写ByteBuffer,请使用put(或StringBuilder使用append((char)

您可以考虑使用更大的基数来缩小数字。

base 36: hy4p6ugr
base 16: 147791288bb
base 10: 1406485563579

答案 2 :(得分:2)

我认为这就是你所要求的(?):

static int toChars(long num, byte[] buffer) {
    if (num < 0) throw new IllegalArgumentException();
    int length = 0;
    do {
        buffer[length++] = (byte)(num % 10 + '0');
    } while ((num /= 10) != 0);
    for (int i = 0, mid = length >> 1, j = length - 1; i < mid; i++, j--) {
        byte tmp = buffer[i];
        buffer[i] = buffer[j];
        buffer[j] = tmp;
    }
    return length;
}

用法:

byte[] buffer = new byte[19]; // 19 = enough for everything up to Long.MAX_VALUE

int length = toChars(51239827493284L, buffer);

System.out.println(new String(buffer, 0, length,
    java.nio.charset.StandardCharsets.US_ASCII));

答案 3 :(得分:1)

据我所见,没有诀窍。

public class Test {

    public static void main(String[] args) {
        byte [] result = new byte[6];
        convert( 123456, result );
        System.out.println( new String( result ) );
    }

    public static void convert( long n, byte [] array ) {
        for (int i = size( n ) - 1; i >= 0; --i) {
            array[i] = (byte)(n % 10 + '0');
            n = n / 10;
        }
    }

    public static int size( long n ) {
        int ret = 0;
        while (n > 0) {
            ret++;
            n /= 10;
        }
        return ret;
    }

}

请注意,这仅适用于正数,并且不检查数组是否足够大以适应数字,您应该在实际代码中执行这两项操作。它无法处理n=0中的小问题。

您可以避免使用size()方法将数组填充到前面,然后将其翻转,但是我不太确定它会为您提供任何性能方面的信息。 #39; d是一个噩梦。

答案 4 :(得分:1)

您可以预先将byte[]分配给最长的长(最长的长度为20个字符),然后将长整齐转换为该数组。

当然,如果你不想在数字17上浪费20个字符,你可以快速计算出长数中的字符数(看它是否大于10 ^ 18,那么如果它大于10 ^ 18等...你可以对数字位进行二进制搜索。)