আমি লংকে বাইট [] এবং জাভাতে ফিরে রূপান্তর করব


159

আমি কীভাবে জাভাতে longএকটি byte[]এবং এ রূপান্তর করব ?

আমি এটিকে একটিতে রূপান্তর longকরার চেষ্টা করছি byte[]যাতে আমি byte[]ওভারের টিসিপি সংযোগটি পাঠাতে সক্ষম হব । অন্যদিকে আমি এটি নিতে byte[]এবং এটিকে আবার একটি রূপান্তর করতে চাই double


অন্য বিকল্প হ'ল মানচিত্র.ট্রান্সফর্মভ্যালিউস, সংগ্রহগুলি রূপান্তর করার জন্য একটি সাধারণ সরঞ্জাম ing docs.guava-libraries.googlecode.com/git-history/release/javadoc/…
রাউল

1
আপনার লক্ষ্যটি যদি একটি দীর্ঘকে বেস 64 এর কয়েকটি সংখ্যায় সংখ্যায় রূপান্তর করতে হয় তবে স্ট্যাকওভারফ্লো.com/q/27559449/32453 দেখুন ।
রজারডপ্যাক

সম্ভবত এটির জোর দেওয়া উচিত যে রূপান্তর পাইপলাইনটি 'দীর্ঘ -> বাইট [] -> দ্বিগুণ', 'দীর্ঘ -> বাইট [] -> দীর্ঘ -> দ্বিগুণ' নয়।
কিরিল গাজাজকভ 11

উত্তর:


230
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();
}

বা বারবার বাইটবফার তৈরি করা এড়াতে কোনও ক্লাসে আবৃত:

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();
    }
}

যেহেতু এটি এত জনপ্রিয় হয়ে উঠছে, আমি কেবল উল্লেখ করতে চাই যে আমি মনে করি আপনি বেশিরভাগ ক্ষেত্রে গুয়ারা জাতীয় লাইব্রেরি ব্যবহার করা ভাল off এবং আপনার যদি গ্রন্থাগারগুলির বিরুদ্ধে কিছু অদ্ভুত বিরোধিতা থাকে, তবে সম্ভবত সম্ভবত দেশীয় জাভা সমাধানের জন্য আপনার এই উত্তরটি বিবেচনা করা উচিত । আমি মনে করি যে আমার উত্তরটি সত্যই এটির পক্ষে গেছে তা হ'ল আপনাকে নিজেরাই সিস্টেমের এন্ডিয়ান-নেস সম্পর্কে চিন্তা করতে হবে না।


3
চতুর ... তবে আপনি প্রতিটি রূপান্তরটির জন্য একটি অস্থায়ী বাইটবফার তৈরি এবং বাতিল করেন। আপনি যদি প্রতি বার্তা এবং / অথবা প্রচুর বার্তা একাধিক দীর্ঘ প্রেরণ করছেন তবে ভাল নয়।
স্টিফেন সি

1
@ স্টেফেন - বাইটবফার কীভাবে ব্যবহার করতে হয় তা প্রদর্শনের জন্য আমি যথেষ্ট করছিলাম, তবে আমি এগিয়ে গিয়ে একটি ইউটিলিটি শ্রেণিতে এটি ব্যবহারের উদাহরণ যুক্ত করেছি।
ব্র্যাড ম্যাস

8
আমি মনে করি যে এখানে বাইটটোলং () পুটটি বাফারের শেষে, পজিশনটি শুরু হওয়ার পরে অবস্থান হিসাবে ব্যর্থ হবে। আমি মনে করি আপনি একটি বাফার আন্ডারফ্লো ব্যতিক্রম পাবেন।
অ্যালেক্স মিলার

11
প্রাক জাভা 8, আপনি যাদু নম্বর এড়াতে Long.BYTES এর পরিবর্তে Long.SIZE / বাইট.SIZE ব্যবহার করতে পারেন।
jvdbogae

8
এই বাইটবফারটির পুনরায় ব্যবহার অত্যন্ত সমস্যাযুক্ত এবং কেবল থ্রেড-সুরক্ষার কারণে নয় অন্যরা মন্তব্য করেছেন। এর মধ্যে কেবল একটি '.ক্লেয়ার ()' দরকার হবে না তবে যা স্পষ্ট নয় তা হ'ল বাইটবফায়ারে .array () কল করা ব্যাকিং অ্যারে বনাম একটি অনুলিপি ফিরিয়ে দিচ্ছে। সুতরাং আপনি যদি বার বার কল করেন এবং অন্যান্য ফলাফল ধরে রাখেন তবে তারা আসলে একই ধরণের অ্যারে যা বারবার পূর্ববর্তী মানগুলি ওভাররাইট করে। নীচে একটি মন্তব্যে হাদুপ লিঙ্কটি সর্বাধিক পারফরম্যান্ট এবং এর মধ্যে যে কোনও সমস্যা এড়ানো যায়।
অ্যারন জিনম্যান


84

আমি প্লেইন বিটওয়াইজ অপারেশনের বিরুদ্ধে বাইটবফার পদ্ধতিটি পরীক্ষা করেছি তবে পরবর্তীটি উল্লেখযোগ্যভাবে দ্রুত।

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;
}

1
ফলাফলের পরিবর্তে | = (b [i] & 0xFF); আমরা কেবল ফলাফলটি ব্যবহার করতে পারি | = b [i]; এবং 0xFF এর সাথে কিছুটা হলেও পরিবর্তন করতে পারে না।
বিপুল

3
@ বিপুল বিটওয়াইস-এবং গুরুত্বপূর্ণ বিষয় কারণ কেবল result |= b[i]বাইট মানটি করার সময় প্রথমে লংতে রূপান্তরিত হবে যা সাইন এক্সটেনশন করে না। মান -128 (হেক্স 0x80) সহ একটি বাইট মান -128 (হেক্স ) সহ একটি দীর্ঘতে পরিণত হবে 0xFFFF FFFF FFFF FF80। রূপান্তর হওয়ার পরে প্রথমে মানগুলি বা: এড একসাথে হয়। , Bitwise-এবং ব্যবহার এই বিরুদ্ধে প্রথম সাইন এক্সটেনশানটি বন্ধ কোন int এবং কাটা করতে বাইট রূপান্তর দ্বারা রক্ষা করে: (byte)0x80 & 0xFF ==> (int)0xFFFF FF80 & 0xFF ==> (int) 0x80। জাভাতে বাইটস কেন স্বাক্ষরিত হয় তা আমার কাছে কিছুটা রহস্য, তবে আমার ধারণা এটি অন্যান্য ধরণের সাথে খাপ খায়।
মস্তিষ্ক

@ ব্রেনস্টর্ম আমি -২৮৮ এর সাথে | = বি [আই] এবং | = (বি [আই] ও ০ এক্সএফএফ) এর সাথে মামলার চেষ্টা করেছি এবং ফলাফলগুলি একই রকম !!
মাহমুদ হানাফি

সমস্যাটি হ'ল শিফটটি প্রয়োগ করার আগে বাইটটি প্রচারিত হয় যা সাইন বিট নিয়ে অদ্ভুত সমস্যা সৃষ্টি করে। সুতরাং আমরা প্রথমে এবং (এবং) 0xFF দিয়ে শিফ্টের সঠিক মান পেতে পারি।
ওয়াটজে

আমি এই ডেটা (ডেটা = নতুন বাইট [] {(বাইট) 0xDB, (বাইট) 0xA7, 0x53, (বাইট) 0xF8, (বাইট) 0xA8, 0x0 সি, 0x66, 0x8);) দীর্ঘ রূপান্তর করতে চেষ্টা করি, তবে এটি ফিরে আসে মিথ্যা মান -2619032330856274424, প্রত্যাশিত মান 989231983928329832
জেফ্রি জ্যাকি

29

যদি আপনি একটি দ্রুত অনিবন্ধিত সংস্করণ সন্ধান করছেন, এটির কৌশলটি করা উচিত, 8 টি দৈর্ঘ্যের "বি" নামে একটি বাইট অ্যারে ধরে নেওয়া:

বাইট [] -> দীর্ঘ

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)};

1
ধন্যবাদ, সেরা!
মিহা_এক্স 64

15

আপনার বাইটটি কেন দরকার []? কেন এটি সকেটে লিখবেন না?

আমি ধরে নিচ্ছি লংয়ের চেয়ে আপনি দীর্ঘ বোঝাচ্ছেন , পরবর্তীটির নাল মানগুলির জন্য অনুমতি দেওয়া দরকার।

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

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

8
আপনি কীভাবে বাইট []] এবং ফিরে রূপান্তর করবেন তা জিজ্ঞাসা করেছিলেন। ভাল উত্তর কিন্তু প্রশ্নের উত্তর দেয় নি। আপনি কেন জিজ্ঞাসা করেছেন কারণ আপনি এটি অপ্রয়োজনীয় বলে ধরে নিচ্ছেন তবে এটি একটি ভুল ধারণা। যদি তিনি ক্রস-ল্যাঙ্গুয়েজ বা ক্রস-প্ল্যাটফর্ম করছেন? ডেটাআউটপুট স্ট্রিম আপনাকে সেখানে সাহায্য করবে না।
ব্যবহারকারী 1132959

4
যদি তিনি ক্রস-ল্যাঙ্গুয়েজ বা ক্রস-প্ল্যাটফর্ম করছেন, তবে একটি বর্ধিত ক্রমে বাইটগুলি প্রেরণ গুরুত্বপূর্ণ। ডকস অনুসারে এই পদ্ধতিটি এটি করে (এটি তাদের "হাই বাইট প্রথমে লিখেছে")। গৃহীত উত্তর দেয় না (এটি ডক্স অনুসারে এটি "বর্তমান ক্রমে" লিখে দেয়)। প্রশ্নটিতে বলা হয়েছে যে তিনি তাদের টিসিপি সংযোগের মাধ্যমে পাঠাতে চান। এটি কেবল byte[]শেষের জন্য একটি উপায়।
ইয়ান ম্যাকলায়ার্ড

3
@ আইএনএমসিএলএইয়ার্ড স্বীকৃত উত্তরটি একটি জ্ঞাত অর্ডার ব্যবহার করে। এটি একটি নতুন তৈরি করে ByteBufferযা ডকস অনুসারে "বাইট বাফারের প্রাথমিক ক্রম সর্বদা BIG_ENDIAN হয়
ডেভিড ফিলিপস

4

অন্তর্নিহিত বাইটআর্যআউটপুট স্ট্রিম সহ একটি ডেটাআউটপুট স্ট্রিমটিতে কেবল দীর্ঘ লিখুন । বাইটআর্যআউটপুট স্ট্রিম থেকে আপনি টু বাইটআরে () এর মাধ্যমে বাইট-অ্যারে পেতে পারেন :

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));       
        }
}

সেই অনুযায়ী অন্যান্য আদিমদের জন্য কাজ করে।

ইঙ্গিত: টিসিপি-র জন্য আপনার ম্যানুয়ালি বাইট [] লাগবে না। আপনি একটি সকেট socket এবং এর স্ট্রিম ব্যবহার করবেন

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

পরিবর্তে.


4

আপনি org.apache.hadoop.hbase.util.Bytes 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

টোলং এবং টোবাইটস পদ্ধতিগুলি দেখুন।

আমি বিশ্বাস করি সফ্টওয়্যার লাইসেন্স আপনাকে কোডের কিছু অংশ নিতে এবং এটি ব্যবহার করতে দেয় তবে দয়া করে এটি যাচাই করুন।


কেন এই বাস্তবায়ন OR এর পরিবর্তে XOR (^ =) ব্যবহার করে? github.com/apache/hbase/blob/master/hbase-common/src/main/java/…
વિજય

3
 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;
    }

2
আপনি অ্যারেলিস্ট এড়িয়ে যেতে পারেন: পাবলিক স্ট্যাটিক বাইট [] লংটোবাইটস (লম্বা l) {দীর্ঘ নাম = l; বাইট [] বাইটস = নতুন বাইট [8]; (int i = bytes.length - 1, i> = 0; i--) {বাইটস [i] = (বাইট) (সংখ্যা এবং 0xff); নাম >> = 8; } প্রত্যাবর্তন বাইটসপ; }
eckes

আসল পদ্ধতিটি নেতিবাচক সংখ্যার সাথে কাজ করে না কারণ এটি অসীম লুপটি পেয়ে যায় (এল! = 0), @ একেসের পদ্ধতিটি 127 এর বেশি সংখ্যার সাথে কাজ করে না কারণ তিনি 127 কারণে বেটে নেতিবাচক যাচ্ছে না account তারা স্বাক্ষরিত হয়।
বড়_ব্যাড_ই

2

আমি আরও একটি উত্তর যুক্ত করব যা দ্রুততম সম্ভব ׂ (হ্যাঁ, স্বীকৃত উত্তরের চেয়েও বেশি), তবে এটি প্রতিটি একক ক্ষেত্রে কার্যকর হবে না। যাইহোক, এটি প্রতিটি কল্পনাপ্রসূত দৃশ্যের জন্য কাজ করবে:

আপনি কেবল স্ট্রিংকে মধ্যবর্তী হিসাবে ব্যবহার করতে পারেন। দ্রষ্টব্য, এটি আপনাকে সঠিক ফলাফল দেবে, যদিও মনে হচ্ছে স্ট্রিং ব্যবহারের ফলে ভুল ফলাফল হতে পারে আপনি দীর্ঘমেয়াদে জানেন যে আপনি "সাধারণ" STRING এর সাথে কাজ করছেন। কার্যকারিতা বাড়াতে এবং কোডটিকে আরও সহজ করার জন্য এটি এমন একটি পদ্ধতি যা এর পরিবর্তে ডেটা স্ট্রিংয়ের উপর চালিত ডেটা স্ট্রিংগুলির জন্য কিছু অনুমান ব্যবহার করা উচিত।

এই পদ্ধতিটি ব্যবহার করার বিষয়টি: আপনি যদি ASCII সারণির শুরুতে এই চিহ্নগুলির মতো কিছু ASCII অক্ষরের সাথে কাজ করছেন তবে নিম্নলিখিত লাইনগুলি ব্যর্থ হতে পারে তবে আসুন এটির মুখোমুখি হন - আপনি সম্ভবত এগুলি কখনও ব্যবহার করবেন না।

এই পদ্ধতিটি ব্যবহারের প্রো: মনে রাখবেন যে বেশিরভাগ লোকেরা সাধারণত কোনও অস্বাভাবিক চরিত্র ছাড়াই কিছু সাধারণ স্ট্রিং নিয়ে কাজ করেন এবং তারপরে পদ্ধতিটি যাওয়ার সহজতম এবং দ্রুততম উপায়।

দীর্ঘ থেকে বাইট []:

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

বাইট [] থেকে দীর্ঘ পর্যন্ত:

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

2
নেক্রোপোস্টিংয়ের জন্য দুঃখিত, তবে এটি ঠিক ভুল। E. g। স্ট্রিং.ভেলিউওফ (0) .getBytes () [0] == 0x30। আশ্চর্য! স্ট্রিং # গেটবাইটস সংখ্যার পরিবর্তে ASCII- এনকোডড ডিজিটাল প্রতীকগুলি প্রত্যাবর্তন করবে: '0'! = 0, তবে '0' == 0x30
কিরিল গামাজকভ

ঠিক আছে যদি আপনি আমার পুরো উত্তরটি পড়ে থাকেন তবে আপনি দেখতে পেয়েছেন আমি উত্তরে নিজেই এটি সম্পর্কে সতর্ক করে দিয়েছি ..
Yonatan Nir

1
আহ, আমি এই বিন্দুটি মিস করেছি যে মধ্যবর্তী বাইট [] ডেটাটিকে (প্রায়) অস্বচ্ছ হিসাবে ধরা হয়। আপনার কৌশলটি এই দৃশ্যের জন্য করবে।
কিরিল গাজাজকভ 11

1

আপনি যদি ইতিমধ্যে OutputStreamসকেটে লিখতে একটি ব্যবহার করছেন, তবে ডেটাআউটপুট স্ট্রিমটি ভাল ফিট হতে পারে। এখানে একটি উদাহরণ:

// 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 প্রাপ্তির দিকে।


0

বাইটবফার.লোকট (8) সাথে .পুটলং (আপত্তি) .আরে ()

public byte[] toBytes(Long obj) {
    if (obj != null) {
      return ByteBuffer.allocate(8).putLong(obj).array();
    return null;
  }

উৎস:

বাইটবফারের অন্যান্য অনেক ব্যবহারের উদাহরণের জন্য:


0

জাভা 8 বা আরও নতুন ব্যবহার করে রূপান্তর byte[]করার জন্য এখানে আরও একটি উপায় রয়েছে long:

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));
}

একটি রূপান্তর করা longবিটওয়াইস-ওআর সাপেক্ষে দুটি পূর্ণসংখ্যার মানের উচ্চ এবং নিম্ন-অর্ডার বিট হিসাবে প্রকাশ করা যেতে পারে। নোট করুন যে ক্লাস toUnsignedLongথেকে এসেছে Integerএবং প্রথম কলটি toUnsignedLongঅতিমাত্রায় হতে পারে।

বিপরীত রূপান্তরটিও অনিবন্ধিত হতে পারে, যেমন অন্যরা উল্লেখ করেছেন।


0

দীর্ঘ এবং বাইটআরে টাইপের জন্য কোটলিন এক্সটেনশনগুলি:

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 এ সম্পূর্ণ কোড দেখতে পারেন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.