IT이야기

Java에서 Long을 바이트[]로 변환한 후 다시 변환하는 방법

cyworld 2022. 5. 10. 22:26
반응형

Java에서 Long을 바이트[]로 변환한 후 다시 변환하는 방법

변환 방법long완전히byte[]자바로 돌아가면?

나는 변환을 시도하고 있다.long완전히byte[]그래서 내가 그 물건을 보낼 수 있도록.byte[]TCP 연결을 통해.반대편에서 나는 그것을 가져가고 싶다.byte[]그리고 그것을 다시 a로 변환한다.double.

public byte[] longToBytes(long x) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.putLong(x);
    return buffer.array();
}

public long bytesToLong(byte[] bytes) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.put(bytes);
    buffer.flip();//need flip 
    return buffer.getLong();
}

또는 반복적으로 ByteBuffer를 만들지 않도록 클래스로 포장:

public class ByteUtils {
    private static ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);    

    public static byte[] longToBytes(long x) {
        buffer.putLong(0, x);
        return buffer.array();
    }

    public static long bytesToLong(byte[] bytes) {
        buffer.put(bytes, 0, bytes.length);
        buffer.flip();//need flip 
        return buffer.getLong();
    }
}

이것이 매우 인기를 얻고 있기 때문에, 나는 단지 당신이 대부분의 경우에 과바와 같은 도서관을 이용하는 것이 더 낫다고 생각한다는 것을 언급하고 싶다.그리고 만약 당신이 도서관에 대해 이상한 반대가 있다면, 당신은 아마도 네이티브 자바 솔루션에 대해 이 대답을 먼저 고려해야 할 것이다.내 답변이 정말 잘 되는 것은 네가 직접 시스템의 최종적인 것에 대해 걱정할 필요가 없다는 것이다.

당신은 구글 과바에서 바이트 변환 방법을 사용할 수 있다.

예:

byte[] bytes = Longs.toByteArray(12345L);

나는 ByteBuffer 방법을 일반 비트 작동에 대해 테스트했지만 후자는 상당히 빠르다.

public static byte[] longToBytes(long l) {
    byte[] result = new byte[8];
    for (int i = 7; i >= 0; i--) {
        result[i] = (byte)(l & 0xFF);
        l >>= 8;
    }
    return result;
}

public static long bytesToLong(final byte[] b) {
    long result = 0;
    for (int i = 0; i < 8; i++) {
        result <<= 8;
        result |= (b[i] & 0xFF);
    }
    return result;
}

Java 8+의 경우 추가된 정적 변수를 사용할 수 있다.

public static byte[] longToBytes(long l) {
    byte[] result = new byte[Long.BYTES];
    for (int i = Long.BYTES - 1; i >= 0; i--) {
        result[i] = (byte)(l & 0xFF);
        l >>= Byte.SIZE;
    }
    return result;
}

public static long bytesToLong(final byte[] b) {
    long result = 0;
    for (int i = 0; i < Long.BYTES; i++) {
        result <<= Byte.SIZE;
        result |= (b[i] & 0xFF);
    }
    return result;
}

빠르게 스크롤되지 않은 버전을 찾는 경우 길이가 8인 "b"라는 바이트 배열을 가정하여 트릭을 실행하십시오.

바이트[] -> 길이

long l = ((long) b[7] << 56)
       | ((long) b[6] & 0xff) << 48
       | ((long) b[5] & 0xff) << 40
       | ((long) b[4] & 0xff) << 32
       | ((long) b[3] & 0xff) << 24
       | ((long) b[2] & 0xff) << 16
       | ((long) b[1] & 0xff) << 8
       | ((long) b[0] & 0xff);

상기의 정확한 대응으로서 긴 -> 바이트[]

byte[] b = new byte[] {
       (byte) lng,
       (byte) (lng >> 8),
       (byte) (lng >> 16),
       (byte) (lng >> 24),
       (byte) (lng >> 32),
       (byte) (lng >> 40),
       (byte) (lng >> 48),
       (byte) (lng >> 56)};

바이트[]가 왜 필요한가?왜 그냥 소켓에 쓰지 않는거지?

보다는 , 후자는 null 값을 허용해야 한다는 뜻인 것 같아.

DataOutputStream dos = new DataOutputStream(
     new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);

DataInputStream dis = new DataInputStream(
     new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();

나는 이 방법이 가장 친근하다고 생각한다.

var b = BigInteger.valueOf(x).toByteArray();

var l = new BigInteger(b);

기본 ByteArrayOutputStream을 사용하여 DataOutputStream에 길게 쓰십시오.ByteArrayOutputStream에서 toByteArray()를 통해 바이트 어레이를 얻을 수 있다.

class Main
{

        public static byte[] long2byte(long l) throws IOException
        {
        ByteArrayOutputStream baos=new ByteArrayOutputStream(Long.SIZE/8);
        DataOutputStream dos=new DataOutputStream(baos);
        dos.writeLong(l);
        byte[] result=baos.toByteArray();
        dos.close();    
        return result;
        }


        public static long byte2long(byte[] b) throws IOException
        {
        ByteArrayInputStream baos=new ByteArrayInputStream(b);
        DataInputStream dos=new DataInputStream(baos);
        long result=dos.readLong();
        dos.close();
        return result;
        }


        public static void main (String[] args) throws java.lang.Exception
        {

         long l=123456L;
         byte[] b=long2byte(l);
         System.out.println(l+": "+byte2long(b));       
        }
}

그에 따라 다른 원시 요소에도 작용한다.

힌트: TCP의 경우 바이트[]가 수동으로 필요하지 않다.소켓 사용 socket그 흐름과 그 흐름들

OutputStream os=socket.getOutputStream(); 
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..

대신에

org.apache에서 구현을 사용할 수 있다.하둡.hbase.util.usil.바이트 http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html

소스 코드는 다음과 같다.

http://grepcode.com/file/repository.cloudera.com/content/repositories/releases/com.cloudera.hbase/hbase/0.89.20100924-28/org/apache/hadoop/hbase/util/Bytes.java#Bytes.toBytes%28long%29

toLong 및 toBytes 방법을 찾아보십시오.

소프트웨어 라이센스로 코드의 일부를 가져와서 사용할 수 있을 것 같은데, 확인해줘.

 public static long bytesToLong(byte[] bytes) {
        if (bytes.length > 8) {
            throw new IllegalMethodParameterException("byte should not be more than 8 bytes");

        }
        long r = 0;
        for (int i = 0; i < bytes.length; i++) {
            r = r << 8;
            r += bytes[i];
        }

        return r;
    }



public static byte[] longToBytes(long l) {
        ArrayList<Byte> bytes = new ArrayList<Byte>();
        while (l != 0) {
            bytes.add((byte) (l % (0xff + 1)));
            l = l >> 8;
        }
        byte[] bytesp = new byte[bytes.size()];
        for (int i = bytes.size() - 1, j = 0; i >= 0; i--, j++) {
            bytesp[j] = bytes.get(i);
        }
        return bytesp;
    }

나는 가능한 한 가장 빠른 답을 하나 더 추가할 것이다. ׂ (그렇지만, 받아들여진 답보다 더 많이), 그러나 그것은 모든 경우에 효과가 없을 것이다.그러나, 그것은 상상할 수 있는 모든 시나리오에 대해 작동할 것이다.

String을 중간으로 간단히 사용할 수 있다."정상" 문자열로 작업하는 것을 알고 있는 한 String을 사용하면 잘못된 결과가 나올 수 있는 것처럼 보이지만, 이것은 올바른 결과를 제공할 것이다.이것은 효율성을 높이고 코드를 단순화하기 위한 방법이며, 그 대가로 그것이 작동하는 데이터 문자열에 몇 가지 가정을 사용해야 한다.

이 방법의 사용 조건:ASCII 표의 시작 부분에서 이러한 기호와 같은 일부 ASCII 문자로 작업하는 경우, 다음 행이 실패할 수 있지만, 직시하자 - 어차피 사용하지 않을 것이다.

이 방법을 사용하는 방법:대부분의 사람들은 보통 특이한 문자 없이 정상적인 현을 가지고 일한다는 것을 기억하라. 그리고 그 방법이 가장 간단하고 빠른 방법이다.

긴 길이에서 바이트[]까지:

byte[] arr = String.valueOf(longVar).getBytes();

바이트[]에서 긴 바이트로:

long longVar = Long.valueOf(new String(byteArr)).longValue();

Long 및 ByteArray 유형을 위한 Kotlin 확장:

fun Long.toByteArray() = numberToByteArray(Long.SIZE_BYTES) { putLong(this@toByteArray) }

private inline fun numberToByteArray(size: Int, bufferFun: ByteBuffer.() -> ByteBuffer): ByteArray =
    ByteBuffer.allocate(size).bufferFun().array()

@Throws(NumberFormatException::class)
fun ByteArray.toLong(): Long = toNumeric(Long.SIZE_BYTES) { long }

@Throws(NumberFormatException::class)
private inline fun <reified T: Number> ByteArray.toNumeric(size: Int, bufferFun: ByteBuffer.() -> T): T {
    if (this.size != size) throw NumberFormatException("${T::class.java.simpleName} value must contains $size bytes")

    return ByteBuffer.wrap(this).bufferFun()
}

내 도서관 https://github.com/ArtemBotnev/low-level-extensions에서 풀코드를 볼 수 있다.

이미 사용 중인 경우OutputStream소켓에 쓰기에는 DataOutputStream이 적합할 수 있다.예를 들면 다음과 같다.

// Assumes you are currently working with a SocketOutputStream.

SocketOutputStream outputStream = ...
long longValue = ...

DataOutputStream dataOutputStream = new DataOutputStream(outputStream);

dataOutputStream.writeLong(longValue);
dataOutputStream.flush();

.shortintfloat, 등. 그런 다음 수신 측에서 DataInputStream을 사용할 수 있다.

여기 변환하는 다른 방법이 있다.byte[]longJava 8 이상 사용:

private static int bytesToInt(final byte[] bytes, final int offset) {
    assert offset + Integer.BYTES <= bytes.length;

    return (bytes[offset + Integer.BYTES - 1] & 0xFF) |
            (bytes[offset + Integer.BYTES - 2] & 0xFF) << Byte.SIZE |
            (bytes[offset + Integer.BYTES - 3] & 0xFF) << Byte.SIZE * 2 |
            (bytes[offset + Integer.BYTES - 4] & 0xFF) << Byte.SIZE * 3;
}

private static long bytesToLong(final byte[] bytes, final int offset) {
    return toUnsignedLong(bytesToInt(bytes, offset)) << Integer.SIZE |
            toUnsignedLong(bytesToInt(bytes, offset + Integer.BYTES));
}

a long비트 와이즈-OR의 영향을 받는 두 정수 값의 고차 및 저차 비트로 표현될 수 있다.는 에서 왔다는 점에 유의하십시오.Integer수업과 첫 번째 방문.toUnsignedLong불필요한 것일 수도 있다.

다른 사람들이 언급했듯이, 반대편 변환도 또한 해제될 수 있다.

부터는 Java 9부터 가 장 은은을 이용하는 것이 가장 좋은 이다.VarHandle, 그것은 긴 배열인 것처럼 바이트 배열로부터 읽게 될 , 성능을 위해 .VarHandle정적인 최종 판을 짜다

static final VarHandle HANDLE = MethodHandles.byteArrayViewVarHandle(Long.TYPE.arrayType(), ByteOrder.nativeOrder());

static long bytesToLong(byte[] bytes, int offset) {
    return (long)HANDLE.get(bytes, offset);
}

static void longToBytes(byte[] bytes, int offset, long value) {
    HANDLE.set(bytes, offset, value);
}
static byte[] longToBytes(Long l) {
    return (l + "").getBytes(StandardCharsets.UTF_8);
}

참조URL: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java

반응형