জাভা বাইটবফার থেকে স্ট্রিং


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
আচ্ছা, তুমি কি চেষ্টা করেছ?
tckmn

6
হ্যাঁ আমি করেছি এবং এটি কাজ করে। কিন্তু আমি অন্য বাস্তবায়নের যা আরো জটিল হয়, মত দেখেছি stackoverflow.com/questions/1252468/...
vikky.rk

1
@ ডুরকনব এট অল। তিনি এনকোডিং অনুপস্থিত এবং তার উদাহরণ (সিনট্যাক্স সংশোধন করা হলে) কাজ করবে তবে তার পদ্ধতিটি এখনও সঠিক নয়।
গুস

উত্তর:


83

সম্পাদনা (2018): @ xinyongCheng দ্বারা সম্পাদিত ভাইবোন উত্তর একটি সহজ পদ্ধতির, এবং এটি গ্রহণযোগ্য উত্তর হওয়া উচিত।

আপনি যদি জানতেন যে বাইটগুলি প্ল্যাটফর্মের ডিফল্ট চরসেটে রয়েছে তবে আপনার পদ্ধতির বিষয়টি যুক্তিসঙ্গত হবে। আপনার উদাহরণে এটি সত্য, কারণ k.getBytes()প্ল্যাটফর্মের ডিফল্ট চরসেটের বাইটগুলি দেয়।

আরও ঘন ঘন, আপনি এনকোডিং নির্দিষ্ট করতে চাইবেন। তবে আপনি যে প্রশ্নটি যুক্ত করেছেন তার চেয়ে এটি করার একটি সহজ উপায় আছে। স্ট্রিং এপিআই এমন একটি পদ্ধতি প্রদান করে যা কোনও নির্দিষ্ট এনকোডিংয়ে স্ট্রিং এবং বাইট [] অ্যারের মধ্যে রূপান্তর করে। এই পদ্ধতিগুলি "যখন ডিকোডিং [এনকোডিং] প্রক্রিয়াতে আরও নিয়ন্ত্রণের প্রয়োজন হয় তখন চরসেটইনকডার / চরসেটডেকোডার ব্যবহার করার পরামর্শ দেয় " "

একটি নির্দিষ্ট এনকোডিংয়ে স্ট্রিং থেকে বাইট পেতে, আপনি একটি ভাইবোনের getBytes () পদ্ধতি ব্যবহার করতে পারেন:

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

একটি স্ট্রিংয়ে একটি নির্দিষ্ট এনকোডিং সহ বাইটস রাখতে, আপনি একটি ভিন্ন স্ট্রিং নির্মাণকারী ব্যবহার করতে পারেন:

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

নোট যে ByteBuffer.array()একটি alচ্ছিক অপারেশন। আপনি যদি কোনও অ্যারে দিয়ে নিজের বাইটবফারটি তৈরি করেন তবে আপনি সরাসরি সেই অ্যারেটি ব্যবহার করতে পারেন। অন্যথায়, আপনি যদি নিরাপদ থাকতে চান, ByteBuffer.get(byte[] dst, int offset, int length)বাফার থেকে বাইট অ্যারেতে বাইট পেতে ব্যবহার করুন ।


এবং ByteBuffer.getফাংশনে, ইনপুটটি আবার বাইটের একটি অ্যারে, আমি এটি কীভাবে পেতে পারি? আবার কে.গেটবাইটস বলার কোনও মানে হয় না, তাই না?
উইলিয়াম কিনান

@ উইলিয়ামকিনাণ - আপনার দেওয়া বাইট [] রয়েছে ByteBuffer.get(byte[] dst, int offset, int length)। আপনি স্ট্রিং () কনস্ট্রাক্টর `স্ট্রিং (বাইট [] বাইটস, ইনট অফসেট, ইনট দৈর্ঘ্য, চরসেট চারসেট) এর সাথে একটি স্ট্রিং তৈরি করতে পারেন। আপনি উভয় কলের জন্য একই অফসেট এবং দৈর্ঘ্যের মানগুলি ব্যবহার করতে পারেন।
অ্যান্ডি টমাস

Java.nio.ByteBuffer এ কোন k.getBytes () পদ্ধতি নেই (ব্যবহার করা সংস্করণে নাও থাকতে পারে)। সুতরাং আমি কে.আররে () পদ্ধতি ব্যবহার করেছি যা বাইট ফিরে আসবে []।
মাদুরাপ্রদীপ

@ মাদুরাপ্রদীপ - প্রশ্ন এবং এই উত্তরের উদাহরণ কোডে, 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 ম্যাপিংয়ের জন্য, স্ট্যাকওভারফ্লো / প্রশ্ন / 9098022/… দেখুন ।
asmaier

এছাড়াও, আপনার মধ্যে সত্যই স্ট্রিংয়ের দরকার নেই, CharBuffer decode()রিটার্নগুলি হ'ল CharSequence(পছন্দ String), যাতে আপনি অতিরিক্ত অনুলিপি এড়াতে এবং সরাসরি ব্যবহার করতে পারেন।
ডেভিড এহরমান

15

এটা চেষ্টা কর:

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

বিশেষ দ্রষ্টব্য। আপনি কোনও স্ট্রিংয়ের এনকোডিং না জেনে সঠিকভাবে কোনও বাইট অ্যারে রূপান্তর করতে পারবেন না।

আশা করি এটা কাজে লাগবে


10
ইউটিএফ -8 সম্ভবত ASCII এর চেয়ে আরও ভাল ডিফল্ট অনুমান?
গুস

3
K.getBytes () ব্যবহারের ওপির ব্যবহারের ভিত্তিতে, নির্দিষ্ট করা উচিত নয়, যা প্ল্যাটফর্মের ডিফল্ট চরসেট ব্যবহার করে।
অ্যান্ডি টমাস

7
সমস্ত বাফার একটি অ্যারে দ্বারা সমর্থন করা হয় না, তাই .array()একটি ব্যতিক্রম নিক্ষেপ করতে পারে।
ডিজিট্রি লেজারকা

সমস্ত বাইট্রাফার .array()পদ্ধতিটি সমর্থন করে না ।
স্কালাউইলিয়াম

3
সাবধান হন! আপনি ব্যবহার করেন তাহলে array(), আপনি আবশ্যক ব্যবহার 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অ্যারেটি ফিরিয়ে দেবে । জিনিয়ং চেং প্রস্তাবিত ফর্মটি আরও ভালভাবে ব্যবহার করুন
লেভ

চারসেটের .decode () একটি ভাল সমাধান, সম্মত। আমার উত্তরের প্রসঙ্গটি দরকারী তথ্য বলে মনে হয় তবে এখনকার চেয়ে অনেক কম।
ফুজাক্স

2
সাবধান হন! আপনি ব্যবহার করেন তাহলে array(), আপনি আবশ্যক ব্যবহার 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);

আপনার স্ট্রিংটি ইউটিএফ -8 হিসাবে ব্যাখ্যা করা হয়েছে, এবং তারপরে আবার আইএসও -8859-1 হিসাবে মুদ্রিত করুন:

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

1

এই প্রশ্নের মূলে কীভাবে স্ট্রিংয়ে বাইট ডিকোড করতে হয়?

এটি জাভা এনআইও চারসেটের সাহায্যে করা যেতে পারে:

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());
  • প্রথমে আমরা একটি চ্যানেল তৈরি করি এবং এটি একটি বাফারে পড়ি
  • তারপরে ডিকোড পদ্ধতিটি ল্যাটিন 1 বাফারকে চার্জার বাফারে ডিকোড করে
  • এরপরে আমরা ফলাফলটি রাখতে পারি, উদাহরণস্বরূপ, একটি স্ট্রিংয়ে

আপনার কোডটি ল্যাটিন 1 থেকে utf8 পর্যন্ত ডিকোড করছে না। আপনার কোডটি সঠিক হওয়ার সাথে সাথে CharBuffer utf8 বাফার কল করা কিছুটা বিভ্রান্তিকর কারণ এটির কোনও এনকোডিং নেই।
বিজন লিন্ডকভিস্ট

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");
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.