Nasıl dönüştürebilirim long
bir etmek byte[]
Java ve arka?
Ben bir TCP bağlantısı üzerinden göndermek mümkün olacak long
bir dönüştürmek için çalışıyorum . Diğer tarafta bunu alıp tekrar a dönüştürmek istiyorum .byte[]
byte[]
byte[]
double
Nasıl dönüştürebilirim long
bir etmek byte[]
Java ve arka?
Ben bir TCP bağlantısı üzerinden göndermek mümkün olacak long
bir dönüştürmek için çalışıyorum . Diğer tarafta bunu alıp tekrar a dönüştürmek istiyorum .byte[]
byte[]
byte[]
double
Yanıtlar:
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();
}
Veya art arda ByteBuffers oluşturmaktan kaçınmak için bir sınıfa sarılır:
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();
}
}
Bu çok popüler hale geldiğinden, vakaların büyük çoğunluğunda Guava gibi bir kütüphane kullanmaktan daha iyi olduğunu düşünüyorum. Kütüphanelere garip bir karşıtlık varsa, muhtemelen bu cevabı yerel java çözümleri için düşünmelisiniz . Bence cevabımın asıl ilgisi bu, sistemin endeksiliği hakkında endişelenmenize gerek olmamasıdır.
Sen kullanabilirsiniz Bayt dönüşüm yöntemleri gelen Google Guava .
Misal:
byte[] bytes = Longs.toByteArray(12345L);
ByteBuffer yöntemini düz bitsel işlemlere karşı test ettim ancak ikincisi önemli ölçüde daha hızlı.
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[] bytes, final int offset) {
long result = 0;
for (int i = offset; i < Long.BYTES + offset; i++) {
result <<= Long.BYTES;
result |= (bytes[i] & 0xFF);
}
return result;
}
result |= b[i]
bayt değeri yapılırken uzun olana dönüştürülür ve bu da uzantıyı imzalar. -128 (hex 0x80
) değerine sahip bir bayt, -128 (hex ) değerine sahip bir uzun haline dönüşür 0xFFFF FFFF FFFF FF80
. Dönüşümden sonraki değerler veya: birlikte düzenlenir. Bitsel-ve Kullanma ilk işareti uzantısı kapalı int ve kesim için bayt dönüştürerek buna karşı korur: (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80
. Java'da baytların neden imzalandığı benim için biraz gizem, ama sanırım diğer türlere de uyuyor.
Hızlı bir kaydedilmemiş sürüm arıyorsanız, bu, "b" adlı bir bayt dizisinin 8 uzunluğunda olduğu varsayılarak hile yapmalıdır:
bayt [] -> uzun
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);
long -> byte [] yukarıdakinin tam karşılığı olarak
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)};
Neden bayt [] 'a ihtiyacınız var? neden sadece sokete yazmıyorsunuz?
Ne demek farz uzun ziyade Long , ikincisi ihtiyaçları boş değerlere izin verme.
DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(socket.getOutputStream()));
dos.writeLong(longValue);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(socket.getInputStream()));
long longValue = dis.readLong();
byte[]
sadece bunun için bir araçtır.
ByteBuffer
dokümanlar göre hangi "bir bayt tampon ilk sipariş her zaman BIG_ENDIAN olduğunu.
Sadece uzun yazmak DataOutputStream altta yatan ile ByteArrayOutputStream . ByteArrayOutputStream öğesinden, byte dizisini toByteArray () üzerinden alabilirsiniz :
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));
}
}
Buna göre diğer ilkel ürünler için de çalışır.
İpucu: TCP için bayt [] 'a manuel olarak ihtiyacınız yoktur. Bir Soket socket
ve akarsuları kullanacaksınız
OutputStream os=socket.getOutputStream();
DataOutputStream dos=new DataOutputStream(os);
dos.writeLong(l);
//etc ..
yerine.
Uygulamayı org.apache.hadoop.hbase.util.Bytes adresinde kullanabilirsiniz http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/util/Bytes.html
Kaynak kodu burada:
ToLong ve toBytes yöntemlerini arayın.
Yazılım lisansının kodun bir bölümünü alıp kullanmanıza izin verdiğine inanıyorum, ancak lütfen bunu doğrulayın.
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;
}
Mümkün olan en hızlı olan başka bir cevap ekleyeceğim ׂ (evet, kabul edilen cevaptan daha fazla), AMA her bir vaka için işe yaramayacak. ANCAK, akla gelebilecek her senaryo için çalışacaktır:
String'i ara olarak kullanabilirsiniz. Not, "NORMAL" STRINGS İLE ÇALIŞTIĞINIZI BİLDİRDİĞİNİZ GİBİ yanlış sonuçlar verebilir gibi görünse de, bu size doğru sonucu verecektir. Bu, etkinliği artırmak ve kodu daha basit hale getirmek için bir yöntemdir ve bunun karşılığında üzerinde çalıştığı veri dizelerinde bazı varsayımlar kullanması gerekir.
Con bu yöntemi kullanarak: ASCII tablosunun başlangıcında bu semboller gibi bazı ASCII karakterleriyle çalışıyorsanız, aşağıdaki satırlar başarısız olabilir, ancak bununla yüzleşelim - muhtemelen bunları asla kullanmayacaksınız.
Bu yöntemi kullanma yanlısı: Çoğu insanın olağandışı karakterleri olmayan bazı normal dizelerle çalıştığını ve ardından yöntemin en basit ve en hızlı yol olduğunu unutmayın.
Uzuntan bayta []:
byte[] arr = String.valueOf(longVar).getBytes();
bayttan [] uzununa:
long longVar = Long.valueOf(new String(byteArr)).longValue();
OutputStream
Sokete yazmak için zaten bir kullanıyorsanız , DataOutputStream uygun olabilir. İşte bir örnek:
// Assumes you are currently working with a SocketOutputStream.
SocketOutputStream outputStream = ...
long longValue = ...
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
dataOutputStream.writeLong(longValue);
dataOutputStream.flush();
İçin benzer yöntemler vardır short
, int
, float
vb Sonra kullanabilirsiniz DataInputStream alıcı tarafında.
ByteBuffer.allocate (8) .putLong (obj) .array () ile:
public byte[] toBytes(Long obj) {
if (obj != null) {
return ByteBuffer.allocate(8).putLong(obj).array();
return null;
}
Kaynak:
ByteBuffer'ın diğer birçok kullanım örneği için:
İşte dönüştürmek için başka bir yol byte[]
için long
Java 8 veya daha yeni kullanılarak:
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 dönüştürülmesi, long
bit-OR'ye tabi iki tamsayı değerinin yüksek ve düşük dereceli bitleri olarak ifade edilebilir. Not toUnsignedLong
dan Integer
sınıfı ve birinci çağrı toUnsignedLong
gereksiz olabilir.
Diğerlerinin de belirttiği gibi ters dönüşüm de açılabilir.
Uzun ve ByteArray tipleri için Kotlin uzantıları:
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()
}
Tam kodu kütüphanemde görebilirsiniz https://github.com/ArtemBotnev/low-level-extensions