बाइट सरणी को स्ट्रिंग में कैसे बदलें और इसके विपरीत?


248

मुझे एंड्रॉइड में बाइट सरणी को स्ट्रिंग में बदलना होगा, लेकिन मेरे बाइट सरणी में नकारात्मक मान हैं।

यदि मैं उस स्ट्रिंग को फिर से बाइट सरणी में परिवर्तित करता हूं, तो मुझे जो मान मिल रहे हैं, वे मूल बाइट सरणी मूल्यों से अलग हैं।

मैं उचित रूपांतरण प्राप्त करने के लिए क्या कर सकता हूं? रूपांतरण करने के लिए मैं जिस कोड का उपयोग कर रहा हूं वह इस प्रकार है:

// Code to convert byte arr to str:
byte[] by_original = {0,1,-2,3,-4,-5,6};
String str1 = new String(by_original);
System.out.println("str1 >> "+str1);

// Code to convert str to byte arr:
byte[] by_new = str1.getBytes();
for(int i=0;i<by_new.length;i++) 
System.out.println("by1["+i+"] >> "+str1);

मैं इस समस्या में फंसा हुआ हूं।


3
आप पहली बार में मनमाने ढंग से द्विआधारी डेटा को स्ट्रिंग में बदलने की कोशिश क्यों कर रहे हैं? पहले से ही वर्णित सभी वर्ण समस्याओं के अलावा, यह भी तथ्य है कि यदि आप ऐसा करते हैं तो आप स्ट्रिंग का दुरुपयोग कर रहे हैं। byte[]आपके बाइनरी डेटा और Stringआपके टेक्स्ट के लिए उपयोग करने में क्या गलत है ?
जोकिम सॉर

8
@ जोशीम - कभी-कभी आपके पास बाहरी उपकरण होते हैं जो स्टोर स्ट्रिंग्स जैसी चीजें कर सकते हैं। आप उस स्थिति में एक बाइट सरणी को एक (किसी तरह से एन्कोडेड) स्ट्रिंग में बदलने में सक्षम होना चाहते हैं।
जेम्स मूर

जवाबों:


377

आपके बाइट सरणी में कुछ एन्कोडिंग होनी चाहिए। यदि आपके पास नकारात्मक मान हैं, तो एन्कोडिंग ASCII नहीं हो सकता है। एक बार जब आप इसका पता लगा लेते हैं, तो आप बाइट्स के एक सेट को स्ट्रिंग का उपयोग करके परिवर्तित कर सकते हैं:

byte[] bytes = {...}
String str = new String(bytes, "UTF-8"); // for UTF-8 encoding

आपके द्वारा उपयोग किए जा सकने वाले एन्कोडिंग का एक समूह है, चारसेट क्लास को देखें सन javadocs


4
@ MauricePerry आप बता सकते हैं कि इसके साथ काम क्यों नहीं होगा UTF-8?
आसिफ मुश्ताक

12
@UnKnown क्योंकि UTF-8 कुछ वर्णों को 2- या 3- बाइट स्ट्रिंग्स के रूप में एन्कोड करता है। हर बाइट सरणी एक मान्य UTF-8-एन्कोडेड स्ट्रिंग नहीं है। ISO-8859-1 एक बेहतर विकल्प होगा: यहां प्रत्येक चरित्र को बाइट के रूप में एन्कोड किया गया है।
मौरिस पेरी

1
यह काम कर सकता है, लेकिन आपको हर कीमत पर स्ट्रिंग कंस्ट्रक्टर का उपयोग करने से बचना चाहिए।
hfontanez

नक्शा करने के लिए एक बाइट (8859-1 के साथ) और कोई अपवाद हैंडलिंग (nio.charset के साथ):String str = new String(bytes, java.nio.charset.StandardCharsets.ISO_8859_1);
iman

1
जावा 1.7 के बाद से, आप नए स्ट्रिंग (बाइट्स, StandardCharsets.UTF_8) का उपयोग कर सकते हैं
ihebiheb

101

के बीच "उचित रूपांतरण" byte[]और Stringस्पष्ट रूप से उस एन्कोडिंग को निर्दिष्ट करना है जिसे आप उपयोग करना चाहते हैं। यदि आप इसके साथ शुरू करते हैं byte[]और यह वास्तव में पाठ डेटा नहीं है, तो कोई "उचित रूपांतरण" नहीं है। Strings पाठ के लिए है, byte[]द्विआधारी डेटा के लिए है, और केवल वास्तव में समझदार बात यह है कि जब तक आप पूरी तरह से नहीं होते हैं, तब तक उनके बीच रूपांतरण करने से बचें

यदि आपको Stringबाइनरी डेटा को रखने के लिए वास्तव में उपयोग करना चाहिए, तो सबसे सुरक्षित तरीका बेस 64 एनकोडिंग का उपयोग करना है ।



4
Base64 और आपने मेरी जान बचाई
mstzn

2
Base64 एन्कोडिंग ने मेरी समस्या हल कर दी। UTF-8 ने सभी इनपुट्स के लिए काम नहीं किया
अल-अलामिन

37

मूल समस्या यह है (मुझे लगता है) कि आप अनजाने में एक चरित्र सेट का उपयोग कर रहे हैं जिसके लिए:

 bytes != encode(decode(bytes))

कुछ मामलों में। UTF-8 इस तरह के एक चरित्र सेट का एक उदाहरण है। विशेष रूप से, बाइट्स के कुछ क्रम UTF-8 में मान्य एनकोडिंग नहीं हैं। यदि UTF-8 डिकोडर इन अनुक्रमों में से एक का सामना करता है, तो यह अपमानजनक बाइट्स को त्यागने या "ऐसे किसी भी चरित्र" के लिए यूनिकोड कोड बिंदु के रूप में डीकोड करने के लिए उत्तरदायी है। स्वाभाविक रूप से, जब आप वर्णों को बाइट्स के रूप में एन्कोड करने का प्रयास करते हैं, तो परिणाम अलग होगा।

समाधान है:

  1. आपके द्वारा उपयोग किए जा रहे वर्ण एन्कोडिंग के बारे में स्पष्ट रहें; एक स्ट्रिंग कंस्ट्रक्टर और String.toByteArrayविधि का उपयोग एक स्पष्ट चारसेट के साथ करें।
  2. अपने बाइट डेटा के लिए सही वर्ण सेट का उपयोग करें ... या वैकल्पिक रूप से एक (जैसे "लैटिन -1" जहां सभी बाइट अनुक्रम वैध यूनिकोड वर्णों का मानचित्र बनाते हैं।
  3. यदि आपकी बाइट्स (वास्तव में) बाइनरी डेटा हैं और आप उन्हें "टेक्स्ट आधारित" चैनल पर प्रसारित / प्राप्त करना चाहते हैं, तो Base64 एन्कोडिंग जैसी किसी चीज़ का उपयोग करें ... जो इस उद्देश्य के लिए डिज़ाइन किया गया है

1
"लैटिन -1" एन्कोडिंग का उपयोग करने की टिप के लिए धन्यवाद!
गोंजो

31

हमें बस Stringसरणी के साथ एक नया निर्माण करने की आवश्यकता है: http://www.mkyong.com/java/how-do-convert-byte-array-to-string-in-java/

String s = new String(bytes);

परिणामी स्ट्रिंग के बाइट्स आपके द्वारा उपयोग किए जाने वाले चार्ट पर निर्भर करते हैं। नई स्ट्रिंग (बाइट्स) और नई स्ट्रिंग (बाइट्स, चारसेट.फोरनाम ("utf-8")) और नई स्ट्रिंग (बाइट्स, चारसेट.फ्रेम ("यूटीएफ -16")) जब आप स्ट्रिंग # कॉल करेंगे तो सभी अलग-अलग बाइट सरणियाँ होंगी। getBytes () (डिफ़ॉल्ट चारसेट के आधार पर)


9
नहीं। परिणामी स्ट्रिंग के बाइट्स आपके द्वारा उपयोग किए जाने वाले वर्ण के आधार पर भिन्न होते हैं। new String(bytes)और new String(bytes, Charset.forName("utf-8"))और new String(bytes, Charset.forName("utf-16"))सभी विभिन्न बाइट सरणियों होगा जब आप कॉल String#getBytes()(डिफ़ॉल्ट चारसेट के आधार पर)
एन एस डू टोइट

1
गुमराह करने वाले। अलग-अलग डिकोड charकरने पर परिणामी का s (और इस प्रकार प्रदर्शित पाठ) Stringअलग-अलग होता है bytes। डिफ़ॉल्ट एन्कोडिंग ( String#getBytes("charset")अन्यथा निर्दिष्ट करने के लिए उपयोग करें) का उपयोग करके बाइट्स में रूपांतरण आवश्यक रूप से भिन्न होगा क्योंकि यह अलग इनपुट को परिवर्तित करता है। स्ट्रिंग्स स्टोर नहीं करते हैं जिससे byte[]वे बनाए गए थे , उनके charपास एन्कोडिंग नहीं है और Stringअन्यथा इसे स्टोर नहीं करता है।
जप्ल

14

उपयोग करना new String(byOriginal)और वापस byte[]उपयोग करना समान मूल्यों के साथ getBytes()दो की गारंटी नहीं देता है byte[]। यह एक कॉल करने के लिए की वजह से है StringCoding.encode(..)जो सांकेतिक शब्दों में बदलना होगा Stringकरने के लिए Charset.defaultCharset()। इस एन्कोडिंग के दौरान, एनकोडर अज्ञात पात्रों को बदलने और अन्य परिवर्तन करने के लिए चुन सकता है। इसलिए, String.getBytes()मूल रूप से कंस्ट्रक्टर के पास जाने के कारण आप एक समान सरणी नहीं लौटा सकते।


9

समस्या क्यों थी: जैसा कि किसी ने पहले ही निर्दिष्ट किया है: यदि आप एक बाइट के साथ शुरू करते हैं [] और यह वास्तव में पाठ डेटा नहीं है, तो कोई "उचित रूपांतरण" नहीं है। स्ट्रिंग्स टेक्स्ट के लिए हैं, बाइट [] बाइनरी डेटा के लिए है, और केवल वास्तव में समझदार बात यह है कि जब तक आप पूरी तरह से नहीं होते हैं, तब तक उनके बीच कनवर्ट करने से बचें।

मैं इस समस्या को देख रहा था जब मैं एक पीडीएफ फाइल से बाइट [] बनाने की कोशिश कर रहा था और फिर उसे स्ट्रिंग में परिवर्तित कर रहा था और फिर स्ट्रिंग को इनपुट के रूप में ले रहा था और वापस फाइल में परिवर्तित कर रहा था।

इसलिए सुनिश्चित करें कि आपका एन्कोडिंग और डिकोडिंग तर्क वैसा ही है जैसा मैंने किया था। मैंने स्पष्ट रूप से बाइट [] को बेस 64 पर एनकोड किया और इसे फिर से फाइल बनाने के लिए डीकोड किया।

यूज-केस: कारण कुछ सीमा के मैं भेजा कोशिश कर रहा था byte[]में request(POST)है और इस प्रक्रिया के रूप में इस प्रकार था:

PDF फ़ाइल >> Base64.encodeBase64 (बाइट []) >> स्ट्रिंग >> रिक्वेस्ट भेजें (POST) >> स्ट्रिंग प्राप्त करें >> Base64.decodeBase64 (बाइट []) >> बाइनरी बनाएँ

यह कोशिश करो और यह मेरे लिए काम किया ..

File file = new File("filePath");

        byte[] byteArray = new byte[(int) file.length()];

        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            fileInputStream.read(byteArray);

            String byteArrayStr= new String(Base64.encodeBase64(byteArray));

            FileOutputStream fos = new FileOutputStream("newFilePath");
            fos.write(Base64.decodeBase64(byteArrayStr.getBytes()));
            fos.close();
        } 
        catch (FileNotFoundException e) {
            System.out.println("File Not Found.");
            e.printStackTrace();
        }
        catch (IOException e1) {
            System.out.println("Error Reading The File.");
            e1.printStackTrace();
        }

6

यह मेरे लिए ठीक काम करता है:

String cd="Holding some value";

स्ट्रिंग से बाइट में परिवर्तित करना []:

byte[] cookie = new sun.misc.BASE64Decoder().decodeBuffer(cd);

बाइट से [] स्ट्रिंग में परिवर्तित करना:

cd = new sun.misc.BASE64Encoder().encode(cookie);

5
private static String toHexadecimal(byte[] digest){
        String hash = "";
    for(byte aux : digest) {
        int b = aux & 0xff;
        if (Integer.toHexString(b).length() == 1) hash += "0";
        hash += Integer.toHexString(b);
    }
    return hash;
}

1
इस सवाल का जवाब नहीं है।
james.garriss

इस सवाल का जवाब नहीं है, लेकिन उपयोगी था 3
आलसी निंजा

5

मैंने कुछ ऐसा नोटिस किया जो किसी भी उत्तर में नहीं है। आप प्रत्येक बाइट को वर्णों के लिए बाइट सरणी में डाल सकते हैं, और उन्हें चार सरणी में रख सकते हैं। फिर स्ट्रिंग है

new String(cbuf)
जहां cbuf चारित्रिक सरणी है। वापस परिवर्तित करने के लिए, स्ट्रिंग के माध्यम से लूप को बाइट्स में से प्रत्येक में बाइट सरणी में डालने के लिए लूप करें, और यह बाइट सरणी पहले की तरह ही होगी।


public class StringByteArrTest {

    public static void main(String[] args) {
        // put whatever byte array here
        byte[] arr = new byte[] {-12, -100, -49, 100, -63, 0, -90};
        for (byte b: arr) System.out.println(b);
        // put data into this char array
        char[] cbuf = new char[arr.length];
        for (int i = 0; i < arr.length; i++) {
            cbuf[i] = (char) arr[i];
        }
        // this is the string
        String s = new String(cbuf);
        System.out.println(s);

        // converting back
        byte[] out = new byte[s.length()];
        for (int i = 0; i < s.length(); i++) {
            out[i] = (byte) s.charAt(i);
        }
        for (byte b: out) System.out.println(b);
    }

}


2

कुछ तरीकों का उपयोग करता है जो बाइट्स की एक सरणी को स्ट्रिंग में परिवर्तित करते हैं। मैंने उन्हें परखा है कि वे अच्छा काम करते हैं।

public String getStringFromByteArray(byte[] settingsData) {

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(settingsData);
    Reader reader = new BufferedReader(new InputStreamReader(byteArrayInputStream));
    StringBuilder sb = new StringBuilder();
    int byteChar;

    try {
        while((byteChar = reader.read()) != -1) {
            sb.append((char) byteChar);
        }
    }
    catch(IOException e) {
        e.printStackTrace();
    }

    return sb.toString();

}

public String getStringFromByteArray(byte[] settingsData) {

    StringBuilder sb = new StringBuilder();
    for(byte willBeChar: settingsData) {
        sb.append((char) willBeChar);
    }

    return sb.toString();

}

2

भले ही

new String(bytes, "UTF-8")

यह सही है कि यह UnsupportedEncodingExceptionआपको एक अपवादित अपवाद से निपटने के लिए मजबूर करता है। एक बाइट सरणी को एक में बदलने के लिए आप जावा 1.6 के बाद से एक अन्य निर्माणकर्ता के रूप में उपयोग कर सकते हैं String:

new String(bytes, StandardCharsets.UTF_8)

यह कोई अपवाद नहीं है।

वापस बदलने के साथ भी किया जाना चाहिए StandardCharsets.UTF_8:

"test".getBytes(StandardCharsets.UTF_8)

फिर से आप चेक किए गए अपवादों से निपटने के लिए बचें।


1

मैं इस विधि के साथ बाइट सरणी को एक स्ट्रिंग में बदलने में सफल रहा:

public static String byteArrayToString(byte[] data){
    String response = Arrays.toString(data);

    String[] byteValues = response.substring(1, response.length() - 1).split(",");
    byte[] bytes = new byte[byteValues.length];

    for (int i=0, len=bytes.length; i<len; i++) {
        bytes[i] = Byte.parseByte(byteValues[i].trim());
    }

    String str = new String(bytes);
    return str.toLowerCase();
}

1

जबकि बेस 64 एन्कोडिंग सुरक्षित है और कोई भी "सही उत्तर" का तर्क दे सकता है, मैं यहां जावा बाइट सरणी को / से जावा स्ट्रिंग के रूप में परिवर्तित करने का तरीका ढूंढ रहा हूं। यही है, जहां बाइट सरणी का प्रत्येक सदस्य अपने स्ट्रिंग समकक्ष में बरकरार रहता है, जिसमें एन्कोडिंग / परिवहन के लिए कोई अतिरिक्त स्थान की आवश्यकता नहीं होती है।

8bit पारदर्शी एनकोडिंग का वर्णन करने वाला यह उत्तर मेरे लिए बहुत उपयोगी था। ISO-8859-1आधारभूत एन्कोडिंग के लिए आवश्यक फुलाए हुए स्थान की आवश्यकताओं के बिना मैंने बाइनरी डेटा के टेराबाइट्स का उपयोग आगे और पीछे सफलतापूर्वक (बाइनरी <-> स्ट्रिंग) करने के लिए किया, इसलिए यह मेरे उपयोग के मामले के लिए सुरक्षित है - YMMV।

यह यह समझाने में भी सहायक था कि कब / क्या प्रयोग करना चाहिए।


0
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;    

private static String base64Encode(byte[] bytes)
{
    return new BASE64Encoder().encode(bytes);
}

private static byte[] base64Decode(String s) throws IOException
{
    return new BASE64Decoder().decodeBuffer(s);
}

क्यों? एक बाइट को स्ट्रिंग में बदलने के लिए बेस 64 के माध्यम से क्यों जाना होगा? ओवरहेड।
james.garriss 11

0

यहां काम करने वाला कोड।

            // Encode byte array into string . TemplateBuffer1 is my bytearry variable.

        String finger_buffer = Base64.encodeToString(templateBuffer1, Base64.DEFAULT);
        Log.d(TAG, "Captured biometric device->" + finger_buffer);


        // Decode String into Byte Array. decodedString is my bytearray[] 
        decodedString = Base64.decode(finger_buffer, Base64.DEFAULT);

-1

दोनों रूपांतरणों में 8-बिट चारसेट निर्दिष्ट करने का प्रयास करें। उदाहरण के लिए ISO-8859-1।


-1

बाइट्स को Stringउपयोग करने से पढ़ें ByteArrayInputStreamऔर इसे BufferedReaderबाइट स्ट्रीम के बजाय चार स्ट्रीम के साथ लपेटें जो बाइट डेटा को स्ट्रिंग में परिवर्तित करता है।

package com.cs.sajal;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class TestCls {

    public static void main(String[] args) {

        String s=new String("Sajal is  a good boy");

        try
        {
        ByteArrayInputStream bis;
        bis=new ByteArrayInputStream(s.getBytes("UTF-8"));

        BufferedReader br=new BufferedReader(new InputStreamReader(bis));
        System.out.println(br.readLine());

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

    }
}

आउटपुट है:

सजल एक अच्छा लड़का है


-1

आप रूपांतरण के लिए लूप के लिए सरल का उपयोग कर सकते हैं:

public void byteArrToString(){
   byte[] b = {'a','b','$'};
   String str = ""; 
   for(int i=0; i<b.length; i++){
       char c = (char) b[i];
       str+=c;
   }
   System.out.println(str);
}


-3

एक स्ट्रिंग चार (16 बिट अहस्ताक्षरित) का एक संग्रह है। इसलिए यदि आप नकारात्मक संख्याओं को एक स्ट्रिंग में बदलने जा रहे हैं, तो वे अनुवाद में खो जाएंगे।


1
-1: यह गलत है। जबकि 'बाइट' जावा में एक हस्ताक्षरित प्रकार है, उन्हें लाइब्रेरी कोड द्वारा अहस्ताक्षरित माना जाता है जो वर्ण सेट एन्कोडिंग और डिकोडिंग करता है।
स्टीफन सी

एक अच्छा उदाहरण क्यों एक अहस्ताक्षरित 8 बिट डेटाटाइप वास्तव में एक भाषा में होना एक अच्छा विचार है। अनावश्यक भ्रम से बचा जाता है; ^)
टॉड

यह अनुमान लगाने में सावधानी बरतें कि जावा चार्ट 16 बिट्स का होगा, जावा के यूटीएफ -16 के कारण, वे 32 बिट्स तक विस्तार कर सकते हैं
जो प्लांट

1
@ वास्तव में हाँ, कुछ यूनिकोड वर्ण जब यूटीएफ -16 के रूप में संग्रहीत होते हैं तो दो कोड पॉइंट्स यानी 32 बिट्स होते हैं। UTF-8 में भी ऐसा ही होता है: कुछ अक्षर दो / तीन / चार कोड बिंदुओं का उपयोग करते हैं, अर्थात 16/24/32 बिट्स। वास्तव में, यही यूटीएफ के बारे में है (यानी यूटीएफ! = यूनिकोड)।
सीएएफएक्सएक्स

1
@ क्या आपको पहला सरोगेट मिलेगा - यानी केवल चरित्र का पहला "आधा"। String.charAt विधि और वर्ण वर्ग के लिए डॉक्स को देखें
CAFxX 12

-3
public class byteString {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub
        String msg = "Hello";
        byte[] buff = new byte[1024];
        buff = msg.getBytes("UTF-8");
        System.out.println(buff);
        String m = new String(buff);
        System.out.println(m);


    }

}

गेटबेट पाने के लिए बहस के रूप में चारसेट एन्कोडिंग पास करें
श्याम श्रीनिवासन

1
आप कोड के अतिरिक्त स्पष्टीकरण के साथ इस उत्तर पर विचार करना चाह सकते हैं।
चार्ली श्लेसीयर

-5

Base64 का उपयोग करें और अपनी समस्या को हल करें। उपयोग करने के लिए बहुत आसान है। http://iharder.sourceforge.net/current/java/base64/


5
केवल एक लिंक से अधिक शामिल करने के लिए इस उत्तर को बेहतर बनाने पर विचार करें। Meta.stackexchange.com/questions/8231/… देखें ।
रोब ह्रस्का
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.