स्ट्रिंग (जावा) को बाइट सरणी में परिवर्तित करना


85

मैं Google एप्लिकेशन इंजन में एक वेब एप्लिकेशन लिख रहा हूं। यह लोगों को मूल रूप से html कोड को संपादित करने की अनुमति देता .htmlहै जो ब्लॉबस्टोर में एक फ़ाइल के रूप में संग्रहीत होता है।

मैं byte[]फ़ाइल में सभी वर्णों को वापस करने के लिए fetchData का उपयोग कर रहा हूँ । मैं HTML कोड को संपादित करने के लिए उपयोगकर्ता के लिए एक html प्रिंट करने का प्रयास कर रहा हूं। सब कुछ महान काम करता है!

यहाँ अब मेरी एकमात्र समस्या है:

बाइट सरणी वापस स्ट्रिंग में कनवर्ट करते समय कुछ समस्याएँ हैं। स्मार्ट कोट्स और एक दो अक्षर काफी मजेदार लग रहे हैं। (? 's या जापानी प्रतीकों आदि) विशेष रूप से यह कई बाइट्स हैं मैं देख रहा हूं कि नकारात्मक मूल्य हैं जो समस्या पैदा कर रहे हैं।

स्मार्ट उद्धरणों के रूप में वापस आ रहे हैं -108और -109बाइट सरणी में। यह क्यों है और मैं सही चरित्र एन्कोडिंग दिखाने के लिए नकारात्मक बाइट्स को कैसे डीकोड कर सकता हूं?


का डुप्लीकेट stackoverflow.com/questions/1536054/...
james.garriss

नमस्ते, मुझे पता है कि यह एक बहुत पुरानी पोस्ट है लेकिन मैं इसी तरह की समस्याओं का सामना कर रहा हूं। मैं ssl के लिए एक मध्य-मध्य प्रॉक्सी बना रहा हूं। मैं जिस समस्या का सामना कर रहा हूं, वह आपकी ही तरह है। मैं सॉकेट को सुनता हूं और डेटा को InputStreamऔर फिर में प्राप्त करता हूं byte[]। अब जब मैं byte[]स्ट्रिंग में बदलने की कोशिश कर रहा हूं (मुझे हमलों के लिए प्रतिक्रिया निकाय का उपयोग करने की आवश्यकता है), मुझे वास्तव में स्मार्ट उद्धरणों और प्रश्नों के निशान से भरे मजेदार अक्षर मिलते हैं और क्या नहीं। मेरा मानना है कि तुम्हारा समस्या मेरा रूप में एक ही के रूप में हम दोनों साथ काम कर रहे है htmlमें byte[]। क्या आप सलाह दे सकते हैं?
पारुल एस

वैसे, मैं Sytem.properties का उपयोग करके अपने सिस्टम के एन्कोडिंग को खोजने के लिए हद तक गया और इसे "Cp1252" पाया। अब, मैंने इस्तेमाल किया String str=new String(buffer, "Cp1252");लेकिन कोई मदद नहीं की।
पारुल एस

जवाबों:


141

बाइट सरणी में एक विशेष एन्कोडिंग में वर्ण होते हैं (जो आपको पता होना चाहिए)। इसे स्ट्रिंग में बदलने का तरीका है:

String decoded = new String(bytes, "UTF-8");  // example for one encoding type

द वे - कच्ची बाइट्स नकारात्मक दशमलव के रूप में प्रकट हो सकती हैं क्योंकि जावा डेटेटाइप byteपर हस्ताक्षर किए गए हैं, यह -128 से 127 तक की सीमा को कवर करता है।


-109 = 0x93: Control Code "Set Transmit State"

मान (-109) UNICODE में एक गैर-मुद्रण योग्य नियंत्रण वर्ण है। तो UTF-8 उस चरित्र स्ट्रीम के लिए सही एन्कोडिंग नहीं है।

0x93"Windows-1252" वह "स्मार्ट उद्धरण" है जिसे आप खोज रहे हैं, इसलिए उस एन्कोडिंग का जावा नाम "Cp1252" है। अगली पंक्ति एक परीक्षण कोड प्रदान करती है:

System.out.println(new String(new byte[]{-109}, "Cp1252")); 

5
मैंने UTF-8 का उपयोग करने की कोशिश की और यह अभी भी बाहर आया है? यह कैसे आता है उन नकारात्मक मूल्यों के लिए एक मानचित्रण नहीं मिल रहा है?
जोश

यूटीएफ -8 में 0x93 एक वैध निरंतरता बाइट है, हालांकि - उस बाइट की उपस्थिति केवल यूटीएफ -8 होने के बारे में बताती है यदि यह पहले दो बिट्स सेट के साथ बाइट के बाद नहीं आती है।
निक जॉनसन

1
@ जोश एंड्रियास बताते हैं कि - क्योंकि जावा के byteडेटाटाइप पर हस्ताक्षर किए गए हैं। सबसे महत्वपूर्ण बाइट सेट के साथ 'नकारात्मक' मान बस बाइट्स हैं। वह यह भी बताता है कि आपके द्वारा उपयोग किए जाने वाले सबसे संभावित चरित्र सेट क्या है - विंडोज -1252। आपको पता होना चाहिए कि संदर्भ या सम्मेलन से किस चरित्र का उपयोग करना है, हालांकि, अनुमान लगाए बिना।
निक जॉनसन

25

जावा 7 और ऊपर

आप StandardCharsets से Stringएक Charsetस्थिर के रूप में अपने इच्छित एन्कोडिंग को कंस्ट्रक्टर के पास भी भेज सकते हैं । यह एन्कोडिंग को पारित करने की तुलना में अधिक सुरक्षित हो सकता है , जैसा कि अन्य उत्तरों में सुझाया गया है।String

उदाहरण के लिए, UTF-8 एन्कोडिंग के लिए

String bytesAsString = new String(bytes, StandardCharsets.UTF_8);

1
यह 2011 से एक उत्तर की पुनरावृत्ति है। -1
james.garriss

2
@ james.garriss मुझे नहीं लगता कि यह कोई बात नहीं है, क्योंकि मैं सिर्फ एक नए निर्माण का उल्लेख कर रहा हूं जावा 7 में एन्कोडिंग को एक स्थिरांक के रूप में पारित करने की अनुमति देता है, जो कि मेरी राय में पिछले एपीआई की तुलना में अच्छा और सुरक्षित है। पहले के उत्तरों में उल्लेख किया गया है जहां एन्कोडिंग को स्ट्रिंग के रूप में पारित किया गया था, यदि बिल्कुल।
davnicwil


5
public class Main {

    /**
     * Example method for converting a byte to a String.
     */
    public void convertByteToString() {

        byte b = 65;

        //Using the static toString method of the Byte class
        System.out.println(Byte.toString(b));

        //Using simple concatenation with an empty String
        System.out.println(b + "");

        //Creating a byte array and passing it to the String constructor
        System.out.println(new String(new byte[] {b}));

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Main().convertByteToString();
    }
}

उत्पादन

65
65
A

5
public static String readFile(String fn)   throws IOException 
{
    File f = new File(fn);

    byte[] buffer = new byte[(int)f.length()];
    FileInputStream is = new FileInputStream(fn);
    is.read(buffer);
    is.close();

    return  new String(buffer, "UTF-8"); // use desired encoding
}

3
यह कोड एक संसाधन को लीक करेगा यदि readएक अपवाद फेंकता है।
रायडवल

4

मैं सुझाव देता हूँ Arrays.toString(byte_array);

यह आपके उद्देश्य पर निर्भर करता है। उदाहरण के लिए, मैं एक बाइट सरणी को बिल्कुल उसी प्रारूप में सहेजना चाहता था, जिस प्रारूप में आप डिबग के समय देख सकते हैं, जो कुछ इस तरह है: [1, 2, 3]यदि आप बाइट्स को चरित्र प्रारूप में परिवर्तित किए बिना ठीक उसी मान को सहेजना चाहते हैं, Arrays.toString (byte_array)तो यह करता है। लेकिन अगर आप बाइट्स के बजाय पात्रों को सहेजना चाहते हैं, तो आपको उपयोग करना चाहिए String s = new String(byte_array)। इस मामले में, चरित्र के प्रारूप में sबराबर के बराबर है [1, 2, 3]


क्या आप इस बारे में अधिक जानकारी दे सकते हैं कि आप यह क्यों सुझाव दे रहे हैं? (क्या यह समस्या को हल करेगा? क्या आप कह सकते हैं कि यह इसे हल क्यों करता है?) धन्यवाद!
डीन जे

यह आपके उद्देश्य पर निर्भर करता है। उदाहरण के लिए, मैं एक बाइट सरणी को बिल्कुल उसी प्रारूप में सहेजना चाहता था, जिस प्रारूप में आप डिबग के समय देख सकते हैं, जो कुछ इस प्रकार है: [1, 2, 3] यदि आप बाइट्स को चरित्र प्रारूप में परिवर्तित किए बिना ठीक उसी मान को सहेजना चाहते हैं, Arrays.toString (byte_array) यह करता है,। लेकिन यदि आप बाइट्स के बजाय वर्णों को सहेजना चाहते हैं, तो आपको स्ट्रिंग s = नया स्ट्रिंग (byte_array) का उपयोग करना चाहिए। इस मामले में, एस चरित्र के प्रारूप में [1, 2, 3] के बराबर है।
प्रश्नकर्ता

@sas, आपको इस जानकारी को अपने उत्तर में स्वयं (इसे संपादित करके) टिप्पणी के रूप में जोड़ना चाहिए। आम तौर पर एसओ पर आपको हमेशा ध्यान रखना चाहिए कि टिप्पणियों को किसी भी बिंदु पर हटाया जा सकता है - वास्तव में महत्वपूर्ण जानकारी उत्तर में ही होनी चाहिए।
जीन ब्रोकेस्ट्रा

3

Andreas_D से पिछला उत्तर अच्छा है। मैं बस यह जोड़ने जा रहा हूँ कि जहाँ भी आप आउटपुट प्रदर्शित कर रहे हैं वहाँ एक फॉन्ट और एक कैरेक्टर एन्कोडिंग होगा और यह कुछ वर्णों का समर्थन नहीं कर सकता है।

यह पता लगाने के लिए कि क्या यह जावा है या आपका प्रदर्शन समस्या है, ऐसा करें:

    for(int i=0;i<str.length();i++) {
        char ch = str.charAt(i);
        System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
    }

जावा ने किसी भी वर्ण को मैप किया होगा जो अज्ञात वर्णों के लिए आधिकारिक वर्ण को 0xfffd नहीं समझ सकता है। अगर आपको ' आउटपुट में, लेकिन यह 0xfffd पर मैप नहीं किया गया है, यह आपका डिस्प्ले फॉन्ट या एन्कोडिंग है जो समस्या है, जावा की नहीं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.