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
소스 코드는 다음과 같다.
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();
.short
int
float
, 등. 그런 다음 수신 측에서 DataInputStream을 사용할 수 있다.
여기 변환하는 다른 방법이 있다.byte[]
로long
Java 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
'IT이야기' 카테고리의 다른 글
Vue.js: 사용자가 로그인하거나 로그인하지 않을 때 Vuex Store 상태를 기준으로 탐색 모음의 버튼 표시/숨기기 (0) | 2022.05.10 |
---|---|
C/C++에 어레이를 복사하는 기능이 있는가? (0) | 2022.05.10 |
Vue js 각 개별 요소의 클래스 전환 (0) | 2022.05.10 |
꼬리 재발은 정확히 어떻게 작동하는가? (0) | 2022.05.10 |
JS에서 api 클래스를 작성하고 Vuex에 전화하여 상태를 변경하는 방법 (0) | 2022.05.10 |