स्ट्रिंग के लिए जावा बाइटबफर


121

क्या यह बाइटबफ़र को स्ट्रिंग में परिवर्तित करने का एक सही तरीका है,

String k = "abcd";
ByteBuffer b = ByteBuffer.wrap(k.getBytes());
String v = new String(b.array());

if(k.equals(v))
    System.out.println("it worked");
else
    System.out.println("did not work");

मैं जो कारण पूछ रहा हूं, वह यह है कि यह बहुत आसान लग रहा है, जबकि अन्य दृष्टिकोण जैसे जावा: बाइटिंग बफ़र से और इससे जुड़ी समस्याएं और अधिक जटिल लग रही हैं।


3
अच्छा, आपने इसे आजमाया?
23

6
हां मैंने किया और यह काम करता है। लेकिन मैंने अन्य कार्यान्वयन देखे हैं जो अधिक जटिल हैं, जैसे stackoverflow.com/questions/1252468/…
vikky.rk

1
@ डॉर्कनोब एट। अल। वह एन्कोडिंग याद कर रहा है और उसका उदाहरण (जब सिंटैक्स सही किया गया है) काम करेगा, लेकिन उसका तरीका अभी भी सही नहीं है।
गस

जवाबों:


83

EDIT (2018): @xinyongCheng द्वारा संपादित सिबलिंग उत्तर एक सरल दृष्टिकोण है, और स्वीकृत उत्तर होना चाहिए।

यदि प्लेटफ़ॉर्म के डिफ़ॉल्ट चार्ट में बाइट्स हैं, तो आपका दृष्टिकोण उचित होगा। आपके उदाहरण में, यह सच है क्योंकि k.getBytes()प्लेटफ़ॉर्म के डिफ़ॉल्ट चारसेट में बाइट्स लौटाता है।

अधिक बार, आप एन्कोडिंग निर्दिष्ट करना चाहेंगे। हालाँकि, आपके द्वारा लिंक किए गए प्रश्न की तुलना में ऐसा करने का एक सरल तरीका है। स्ट्रिंग एपीआई एक विशेष एन्कोडिंग में स्ट्रिंग और एक बाइट [] सरणी के बीच परिवर्तित करने वाले तरीके प्रदान करता है। ये विधियाँ CharsetEncoder / CharsetDecoder का उपयोग करने का सुझाव देती हैं "जब डिकोडिंग [एन्कोडिंग] प्रक्रिया पर अधिक नियंत्रण आवश्यक होता है।"

किसी विशेष एन्कोडिंग में स्ट्रिंग से बाइट्स प्राप्त करने के लिए, आप एक भाई getBytes () विधि का उपयोग कर सकते हैं:

byte[] bytes = k.getBytes( StandardCharsets.UTF_8 );

एक स्ट्रिंग में एक विशेष एन्कोडिंग के साथ बाइट्स लगाने के लिए, आप एक अलग स्ट्रिंग निर्माता का उपयोग कर सकते हैं:

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

ध्यान दें कि ByteBuffer.array()एक वैकल्पिक ऑपरेशन है। यदि आपने किसी सरणी के साथ अपने बाइटबफ़र का निर्माण किया है, तो आप सीधे उस सरणी का उपयोग कर सकते हैं। अन्यथा, यदि आप सुरक्षित रहना चाहते हैं, तो ByteBuffer.get(byte[] dst, int offset, int length)बाइट से बाइट पाने के लिए बाइट सरणी में उपयोग करें।


और ByteBuffer.getफ़ंक्शन में, इनपुट फिर से बाइट्स की एक सरणी है, मैं इसे कैसे प्राप्त कर सकता हूं? यह फिर से k.getbytes कहने का कोई मतलब नहीं है, यह करता है?
विलियम कीनन

@WilliamKinaan - आपके पास बाइट [] है जिसे आपने खिलाया है ByteBuffer.get(byte[] dst, int offset, int length)। आप इसे स्ट्रिंग () कंस्ट्रक्टर `स्ट्रिंग (बाइट [] बाइट्स, इंट ऑफ़सेट, इंट लेंथ, चारसेट चारसेट) के साथ एक स्ट्रिंग बना सकते हैं। आप दोनों कॉल के लिए समान ऑफसेट और लंबाई मान का उपयोग कर सकते हैं।
एंडी थॉमस

Java.nio.ByteBuffer में कोई k.getBytes () विधि नहीं है (हो सकता है कि जो संस्करण मैं उपयोग नहीं कर रहा हूं)। तो मैंने k.array () पद्धति का उपयोग किया जो बाइट को वापस कर देगा []।
मादुरा प्रदीप

@MaduraPradeep - प्रश्न और इस उत्तर में उदाहरण कोड में, kएक स्ट्रिंग है, न कि एक बाइटफायर।
एंडी थॉमस

ज्ञात हो कि यूटीएफ -8 बाइट्स को स्ट्रिंग्स और इसके विपरीत में परिवर्तित करने के लिए इष्टतम चार्ट नहीं हो सकता है। बाइट्स को 1 से 1 मैपिंग के लिए बेहतर उपयोग के लिए ISO-8859-1, stackoverflow.com/questions/9098022/…
asmaier

102

एंडी थॉमस द्वारा उल्लिखित ByteBufferएक Stringबिना किसी समस्या के डिकोड करने के लिए सरल दृष्टिकोण है ।

String s = StandardCharsets.UTF_8.decode(byteBuffer).toString();

2
ज्ञात हो कि यूटीएफ -8 बाइट्स को स्ट्रिंग्स और इसके विपरीत में परिवर्तित करने के लिए इष्टतम चार्ट नहीं हो सकता है। आईएसओ-8859-1 का बेहतर उपयोग करने के लिए बाइट्स की 1-टू -1 मैपिंग के लिए, stackoverflow.com/questions/9098022/… देखें ।
asmaier

इसके अलावा, आपको वास्तव में एक स्ट्रिंग की आवश्यकता नहीं है , CharBuffer decode()रिटर्न एक CharSequence(जैसे String) है, इसलिए आप एक अतिरिक्त प्रतिलिपि से बच सकते हैं और इसे सीधे उपयोग कर सकते हैं।
डेविड एहरमन

15

इसे इस्तेमाल करे:

new String(bytebuffer.array(), "ASCII");

एनबी। आप सही ढंग से एक बाइट सरणी को इसके एन्कोडिंग को जाने बिना स्ट्रिंग में नहीं बदल सकते।

आशा है कि ये आपकी मदद करेगा


10
UTF-8 शायद ASCII से बेहतर डिफ़ॉल्ट अनुमान है?
गस

3
ओपी को k.getBytes () के उपयोग को देखते हुए निर्दिष्ट नहीं किया जाना चाहिए, जो प्लेटफ़ॉर्म के डिफ़ॉल्ट चारसेट का उपयोग करता है।
एंडी थॉमस

7
सभी बफ़र्स एक सरणी द्वारा समर्थित नहीं हैं, इसलिए .array()अपवाद फेंक सकते हैं।
द्ज़मिट्री लेज़रका

सभी बाइटबफर्स .array()विधि का समर्थन नहीं करते हैं ।
स्कालाविलियम

3
सावधान! यदि आप उपयोग करते हैं array(), तो आपको सरणी में सही स्थिति पर शुरू करने के लिए भी उपयोग करना चाहिएarrayOffset() ! यह एक सूक्ष्म नुकसान है, क्योंकि आमतौर पर arrayOffset () 0 है; लेकिन उन दुर्लभ मामलों में जहां यह नहीं है, अगर आप इसे ध्यान में नहीं रखते हैं, तो आपको कठिन कीड़े मिलेंगे।
जैतून

13

केवल इंगित करना चाहता था, यह मान लेना सुरक्षित नहीं है कि बाइटबफर (।) हमेशा काम करेगा।

byte[] bytes;
if(buffer.hasArray()) {
    bytes = buffer.array();
} else {
    bytes = new byte[buffer.remaining()];
    buffer.get(bytes);
}
String v = new String(bytes, charset);

आमतौर पर अपने उपयोग के मामले के आधार पर बफर.हासरे () हमेशा सही या गलत होगा। व्यवहार में, जब तक आप वास्तव में किसी भी परिस्थिति में काम नहीं करना चाहते हैं, तब तक उस शाखा को अनुकूलित करना सुरक्षित है जिसकी आपको आवश्यकता नहीं है। लेकिन बाकी के उत्तर बाइटबफ़र के साथ काम नहीं कर सकते हैं जो कि बाइटबफ़र.ऑलोकैटडायरेक्ट () के माध्यम से बनाया गया है।


यदि बफ़र ByteBuffer.wrap(bytes, offset, size)कारखाने के माध्यम से बनाया .array()गया है तो संपूर्ण bytesसरणी वापस आ जाएगी । Xinyong चेंग ने सुझाए गए फॉर्म का बेहतर उपयोग किया
Lev Kuznetsov

.सेटसेट पर .d timecode () एक बेहतर समाधान है, सहमत है। मुझे लगता है कि मेरे उत्तर का संदर्भ उपयोगी जानकारी है, लेकिन अभी बहुत कम है।
फुवजैक्स

2
सावधान! यदि आप उपयोग करते हैं array(), तो आपको सरणी में सही स्थिति पर शुरू करने के लिए भी उपयोग करना चाहिएarrayOffset() ! यह एक सूक्ष्म नुकसान है, क्योंकि आमतौर पर arrayOffset () 0 है; लेकिन उन दुर्लभ मामलों में जहां यह नहीं है, अगर आप इसे ध्यान में नहीं रखते हैं, तो आपको कठिन कीड़े मिलेंगे।
जैतून

8

केवल कॉल करने के लिए संदर्भित उत्तर array()बिल्कुल सही नहीं हैं: जब बफर आंशिक रूप से भस्म हो गया है, या किसी सरणी के एक हिस्से का उल्लेख कर रहा है (आप ByteBuffer.wrapकिसी दिए गए ऑफसेट पर एक सरणी बना सकते हैं , जरूरी नहीं कि शुरुआत से ही), हमें इसका हिसाब देना होगा हमारी गणना में। यह सामान्य समाधान है जो सभी मामलों में बफ़र्स के लिए काम करता है (एन्कोडिंग को कवर नहीं करता है):

if (myByteBuffer.hasArray()) {
    return new String(myByteBuffer.array(),
        myByteBuffer.arrayOffset() + myByteBuffer.position(),
        myByteBuffer.remaining());
} else {
    final byte[] b = new byte[myByteBuffer.remaining()];
    myByteBuffer.duplicate().get(b);
    return new String(b);
}

एन्कोडिंग से संबंधित चिंताओं के लिए, एंडी थॉमस का जवाब देखें।


1

ध्यान दें (एन्कोडिंग मुद्दे से अलग) कि लिंक किए गए कुछ अधिक जटिल कोड बाइटबफ़र के "सक्रिय" भाग को प्रश्न में लेने की परेशानी में जाते हैं (उदाहरण के लिए स्थिति और सीमा का उपयोग करके), बजाय सभी बाइट्स को एन्कोडिंग के। संपूर्ण बैकिंग सरणी में (इन उत्तरों में कई उदाहरण हैं)।


1

स्ट्रिंग को बाइट बफ़र में बदलें, फिर बाइट बफ़र से वापस स्ट्रिंग में जावा का उपयोग करके:

import java.nio.charset.Charset;
import java.nio.*;

String babel = "obufscate thdé alphebat and yolo!!";
System.out.println(babel);
//Convert string to ByteBuffer:
ByteBuffer babb = Charset.forName("UTF-8").encode(babel);
try{
    //Convert ByteBuffer to String
    System.out.println(new String(babb.array(), "UTF-8"));
}
catch(Exception e){
    e.printStackTrace();
}

जो पहले मुद्रित नंगे स्ट्रिंग को प्रिंट करता है, और फिर बाइटबफ़र को सरणी () में डाला जाता है:

obufscate thdé alphebat and yolo!!
obufscate thdé alphebat and yolo!!

इसके अलावा यह मेरे लिए मददगार था, स्ट्रिंग को आदिम बाइट्स तक कम करने से यह पता लगाने में मदद मिल सकती है कि क्या हो रहा है:

String text = "こんにちは";
//convert utf8 text to a byte array
byte[] array = text.getBytes("UTF-8");
//convert the byte array back to a string as UTF-8
String s = new String(array, Charset.forName("UTF-8"));
System.out.println(s);
//forcing strings encoded as UTF-8 as an incorrect encoding like
//say ISO-8859-1 causes strange and undefined behavior
String sISO = new String(array, Charset.forName("ISO-8859-1"));
System.out.println(sISO);

आपके स्ट्रिंग की UTF-8 के रूप में व्याख्या की जाती है, और फिर ISO-8859-1 के रूप में फिर से:

こんにちは
ããã«ã¡ã¯

1

इस सवाल का मूल यह है कि बाइट्स को स्ट्रिंग में कैसे डिकोड किया जाए?

यह जावा NIO चारसेट के साथ किया जा सकता है:

public final CharBuffer decode(ByteBuffer bb)

FileChannel channel = FileChannel.open(
  Paths.get("files/text-latin1.txt", StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);

CharSet latin1 = StandardCharsets.ISO_8859_1;
CharBuffer latin1Buffer = latin1.decode(buffer);

String result = new String(latin1Buffer.array());
  • पहले हम एक चैनल बनाते हैं और इसे एक बफर में पढ़ते हैं
  • तब डीकोड विधि एक लैटिन बफर को एक चार बफर को डीकोड करता है
  • उदाहरण के लिए, हम स्ट्रिंग में, परिणाम डाल सकते हैं

आपका कोड latin1 से utf8 तक डिकोडिंग नहीं है। जबकि आपका कोड सही है, CharBuffer utf8Buffer को कॉल करना कुछ भ्रामक है क्योंकि इसमें कोई एन्कोडिंग नहीं है।
ब्योर्न लिंडक्विस्ट

0
private String convertFrom(String lines, String from, String to) {
    ByteBuffer bb = ByteBuffer.wrap(lines.getBytes());
    CharBuffer cb = Charset.forName(to).decode(bb);
    return new String(Charset.forName(from).encode(cb).array());
};
public Doit(){
    String concatenatedLines = convertFrom(concatenatedLines, "CP1252", "UTF-8");
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.