কিভাবে uint8 অ্যারে বেস 64 এনকোড স্ট্রিং রূপান্তর করতে?


90

আমি একটি ওয়েবসকেট কম्यूनিকেশন পেয়েছি, আমি বেস ed৪ টি এনকোডেড স্ট্রিংটি পেয়েছি, এটি uint8 এ রূপান্তর করব এবং এটিতে কাজ করব, তবে এখন আমাকে ফেরত পাঠানো দরকার, আমি uint8 অ্যারে পেয়েছি এবং এটি বেস 64 স্ট্রিংয়ে রূপান্তর করতে হবে, তাই আমি এটি পাঠাতে পারি। আমি এই রূপান্তরটি কীভাবে করব?



"অ্যারেবফার থেকে বেস64 এনকোড স্ট্রিং" প্রশ্নটিতে আরও ভাল সমাধান রয়েছে যা সমস্ত অক্ষর পরিচালনা করে। stackoverflow.com/questions/9267899/...
স্টিভ Hanov

উত্তর:


16

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

সুতরাং আমি একটি সরাসরি রূপান্তর ফাংশন বাস্তবায়িত করেছি যা ইনপুট নির্বিশেষে ঠিক কাজ করে। এটি আমার মেশিনে প্রতি সেকেন্ডে প্রায় 5 মিলিয়ন বাইট রূপান্তর করে।

https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727


বেস 64 এফসি কেবল স্ট্রিং তৈরি করার চেয়ে দ্রুত স্ট্রিংগুলির অ্যারে হিসাবে রয়েছে? "ABCDEFG..."?
গার গডফ্রে

163

যদি আপনার ডেটাতে মাল্টি-বাইট সিকোয়েন্স থাকতে পারে (কোনও সরল ASCII ক্রম নয়) এবং আপনার ব্রাউজারে টেক্সটডেকোডার রয়েছে , তবে আপনার ডেটা ডিকোড করতে আপনার এটি ব্যবহার করা উচিত (টেক্সটডেকোডারটির জন্য প্রয়োজনীয় এনকোডিং নির্দিষ্ট করুন):

var u8 = new Uint8Array([65, 66, 67, 68]);
var decoder = new TextDecoder('utf8');
var b64encoded = btoa(decoder.decode(u8));

আপনার যদি এমন ব্রাউজারগুলিকে সমর্থন করতে হয় যা টেক্সটডেকোডার (বর্তমানে কেবলমাত্র আইই এবং এজ) নেই, তবে টেক্সটডেকডার পলফিল ব্যবহার করা সবচেয়ে ভাল বিকল্প ।

যদি আপনার ডেটাতে সরল ASCII থাকে (মাল্টিবাইট ইউনিকোড / ইউটিএফ -8 নয়) তবে একটি সহজ বিকল্প ব্যবহার করে String.fromCharCodeএটি সর্বজনীনভাবে সমর্থনযোগ্য হওয়া উচিত:

var ascii = new Uint8Array([65, 66, 67, 68]);
var b64encoded = btoa(String.fromCharCode.apply(null, ascii));

এবং বেস 64 স্ট্রিংটি একটি ইউন্ট 8 অ্যারেতে ফিরে ডিকোড করতে:

var u8_2 = new Uint8Array(atob(b64encoded).split("").map(function(c) {
    return c.charCodeAt(0); }));

আপনার যদি খুব বড় অ্যারে বাফার থাকে তবে অ্যাপ্লিকেশনটি ব্যর্থ হতে পারে এবং আপনাকে বাফারটি ছিন্ন করতে হতে পারে (@ রোহিতস্যাঙ্গার পোস্টের উপর ভিত্তি করে)। আবার, মনে রাখবেন যে এটি শুধুমাত্র সঠিক যদি আপনার বাফারটিতে কেবল নন-মাল্টবাইট ASCII অক্ষর থাকে:

function Uint8ToString(u8a){
  var CHUNK_SZ = 0x8000;
  var c = [];
  for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
    c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
  }
  return c.join("");
}
// Usage
var u8 = new Uint8Array([65, 66, 67, 68]);
var b64encoded = btoa(Uint8ToString(u8));

4
এটি ফায়ারফক্সে আমার জন্য কাজ করছে, তবে ক্রোম "আনকচড রেঞ্জেরর: সর্বাধিক কল স্ট্যাকের আকার ছাড়িয়েছে" (বিটিওএ করছে) দিয়ে চোক করে।
মাইকেল পাউলুকোনিস

4
@ মিশেলপলুকোনিস আমার অনুমান যে এটি আসলে স্ট্রিং.ফর্মচর কোড.এপ্লাই যার ফলে স্ট্যাকের আকার অতিক্রম করা হচ্ছে। আপনার যদি খুব বড় Uint8Array থাকে তবে সম্ভবত এটি প্রয়োগের পরিবর্তে আপনাকে পুনরাবৃত্তভাবে স্ট্রিংটি তৈরি করতে হবে। প্রয়োগ () কলটি আপনার অ্যারের প্রতিটি উপাদানকে চ্যারকোড থেকে প্যারামিটার হিসাবে পাঠিয়ে দিচ্ছে, সুতরাং অ্যারেটি যদি 128000 বাইট দীর্ঘ হয় তবে আপনি 128000 পরামিতি সহ একটি ফাংশন কল করার চেষ্টা করবেন যা স্ট্যাকটি ফুঁ দেওয়ার সম্ভাবনা রয়েছে।
কনক

4
ধন্যবাদ আমার যা দরকার ছিল তা হ'ল 21btoa(String.fromCharCode.apply(null, myArray))
গ্লেন লিটল

29
বাইট অ্যারে বৈধ ইউনিকোড না হলে এটি কাজ করে না।
মেলাব

11
বেস 64 নং স্ট্রিংয়ে বা মধ্যে কোনও মাল্টিবাইট অক্ষর নেই Uint8ArrayTextDecoderএখানে ব্যবহার করা একেবারেই ভুল জিনিস, কারণ আপনার যদি Uint8Array128..255 রেঞ্জের বাইট থাকে তবে টেক্সট ডিকোডার ভুলভাবে তাদের ইউনিকোড অক্ষরে রূপান্তরিত করে, যা বেস 64 কে রূপান্তরিত করে।
রিভ

26

জাভাস্ক্রিপ্টের জন্য খুব সহজ সমাধান এবং পরীক্ষা!

ToBase64 = function (u8) {
    return btoa(String.fromCharCode.apply(null, u8));
}

FromBase64 = function (str) {
    return atob(str).split('').map(function (c) { return c.charCodeAt(0); });
}

var u8 = new Uint8Array(256);
for (var i = 0; i < 256; i++)
    u8[i] = i;

var b64 = ToBase64(u8);
console.debug(b64);
console.debug(FromBase64(b64));

4
সবচেয়ে পরিষ্কার সমাধান!
13:30

নিখুঁত সমাধান
হারিস উর রেহমান

4
এটি বড় ডেটাতে ব্যর্থ হয় (যেমন চিত্রগুলি)RangeError: Maximum call stack size exceeded
ম্যাক্সিম খখরিয়কভ

21

আপনি যদি নোড.জেএস ব্যবহার করেন তবে আপনি এই কোডটি ইউিন্ট 8আর্রে বেস 64 এ রূপান্তর করতে পারেন

var b64 = Buffer.from(u8).toString('base64');

4
পারফরম্যান্সের ক্ষেত্রে এটি হ্যান্ড রোলড ফাংশনগুলির পরে একটি ভাল উত্তর।
বেন লিয়ানাজ

4
অসাধারণ! ধন্যবাদ সর্বকালের সেরা উত্তর
অ্যালান

18
function Uint8ToBase64(u8Arr){
  var CHUNK_SIZE = 0x8000; //arbitrary number
  var index = 0;
  var length = u8Arr.length;
  var result = '';
  var slice;
  while (index < length) {
    slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length)); 
    result += String.fromCharCode.apply(null, slice);
    index += CHUNK_SIZE;
  }
  return btoa(result);
}

আপনার যদি খুব বড় Uint8Araray থাকে তবে আপনি এই ফাংশনটি ব্যবহার করতে পারেন। এটি জাভাস্ক্রিপ্টের জন্য, ফাইলআরডার পড়ার ক্ষেত্রেএএসআর্রে বাফার ক্ষেত্রে কার্যকর হতে পারে।


4
মজার বিষয় হচ্ছে, ক্রোমে আমি এটি 300kb + বাফারে টাইম করেছিলাম এবং এটিকে বাইট বাই বাইট করার চেয়ে কিছুটা ধীর করে দেওয়ার মতো কাজগুলিতে করে দেখতে পেলাম। এটি আমাকে অবাক করে দিয়েছে।
ম্যাট

@ ম্যাট আকর্ষণীয় এটি সম্ভব যে এর মধ্যে, ক্রোম এখন এই রূপান্তরটি সনাক্ত করেছে এবং এর জন্য একটি নির্দিষ্ট অপ্টিমাইজেশন রয়েছে এবং ডেটা ছাঁটাই করা এর কার্যকারিতা হ্রাস করতে পারে।
কনক

4
এটি নিরাপদ নয়, তাই না? যদি আমার খণ্ডের সীমানাটি মাল্টি-বাইট ইউটিএফ 8 এনকোডেড চরিত্রের মাধ্যমে কাটা যায়, তবে চ্যারকোড () থেকে সীমানার উভয় পাশের বাইটগুলি থেকে বুদ্ধিমান অক্ষর তৈরি করতে সক্ষম হবেন না, তাই না?
জেনস

4
@ জেনস String.fromCharCode.apply()পদ্ধতিগুলি ইউটিএফ -8 পুনরুত্পাদন করতে পারে না: ইউটিএফ -8 অক্ষর দৈর্ঘ্যে এক বাইট থেকে চার বাইটে পরিবর্তিত হতে পারে, তবুও String.fromCharCode.apply()ইউআইএনটি 8 এর বিভাগগুলিতে একটি ইউআইএনটি 8 অ্যারে পরীক্ষা করে, তাই এটি ভুলভাবে প্রতিটি চরিত্রকে প্রতিবেশীর ঠিক এক বাইট লম্বা এবং স্বতন্ত্র বলে ধরে নেয় বেশী। ইনপুট UInt8Arrey এ এনকোড করা অক্ষরগুলি সমস্তই ASCII (একক-বাইট) পরিসরে অন্তর্ভুক্ত হওয়ার সাথে সাথে এটি যথাযথভাবে কাজ করবে, তবে এটি সম্পূর্ণ ইউটিএফ -8 পুনরুত্পাদন করতে পারে না। এর জন্য আপনার টেক্সটডেকোডার বা একটি অনুরূপ অ্যালগরিদম দরকার ।
জেমি বার্চ

4
@ জেনস কোন বাইনারি ডেটা অ্যারেতে মাল্টি-বাইট ইউটিএফ 8 এনকোডেড অক্ষরগুলি? আমরা এখানে ইউনিকোড স্ট্রিংগুলি নিয়ে কাজ করছি না, তবে স্বেচ্ছাসেবী বাইনারি ডেটার সাথে, যা utf-8 কোডপয়েন্ট হিসাবে বিবেচিত হবে না।
রিভ

0

এখানে এটির জন্য একটি জেএস ফাংশন রয়েছে:

এই ফাংশনটির প্রয়োজন কারণ ক্রাশটি pushManager.subs সাবস্ক্রাইব এখনও পর্যন্ত https://bugs.chromium.org/p/chromium/issues/detail?id=802280 এ অ্যাপ্লিকেশন সার্ভারকি-এর মান হিসাবে একটি বেস 64 এনকোডড স্ট্রিং গ্রহণ করে না

function urlBase64ToUint8Array(base64String) {
  var padding = '='.repeat((4 - base64String.length % 4) % 4);
  var base64 = (base64String + padding)
    .replace(/\-/g, '+')
    .replace(/_/g, '/');

  var rawData = window.atob(base64);
  var outputArray = new Uint8Array(rawData.length);

  for (var i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

4
এটি বেস 64 কে ইউন্ট 8আরে রূপান্তর করে। তবে প্রশ্নটি জিজ্ঞাসা করে যে কীভাবে Uint8Array কে বেস 64 তে রূপান্তর করা যায়
ব্যারি মাইকেল ডয়েল

0

খাঁটি জেএস - কোনও স্ট্রিং মিডলস্টেপ নেই (কোনও বিটিওএ নেই)

নীচের সমাধানে আমি স্ট্রিংতে রূপান্তর বাদ দিই। আইডিইএ অনুসরণ করছে:

  • 3 বাইট (3 অ্যারে উপাদান) যোগ দিন এবং আপনি 24 বিট পাবেন
  • 24 বিট চারটি 6-বিট সংখ্যায় বিভক্ত করুন (যা 0 থেকে 63 পর্যন্ত মান নেয়)
  • বেস নম্বর 64 বর্ণমালায় সূচক হিসাবে সেই সংখ্যাগুলি ব্যবহার করুন
  • কোণার কেস: যখন ইনপুট বাইট অ্যারের দৈর্ঘ্য 3 দ্বারা বিভক্ত না হয় তারপরে যোগ করুন =বা ==ফলস্বরূপ

নীচের সমাধানটি 3-বাইট অংশগুলিতে কাজ করে তাই এটি বড় অ্যারেগুলির পক্ষে ভাল। বেস 64 কে বাইনারি অ্যারেতে (রূপবিহীন atob) রূপান্তর করার অনুরূপ সমাধানটি এখানে


আমি কমপ্যাকটিসটি পছন্দ করি তবে বাইনারি সংখ্যার প্রতিনিধিত্ব করে স্ট্রিংগুলিতে রূপান্তর করা এবং তারপরে ফিরে গৃহীত সমাধানের চেয়ে অনেক ধীর।
গার গডফ্রে

0

Uint8 অ্যারে বেস 64 কে এনকোড করা স্ট্রিংয়ে রূপান্তর করতে নিম্নলিখিতটি ব্যবহার করুন

function arrayBufferToBase64(buffer) {
            var binary = '';
            var bytes = [].slice.call(new Uint8Array(buffer));
            bytes.forEach((b) => binary += String.fromCharCode(b));
            return window.btoa(binary);
        };


-3

যদি আপনি চান সমস্ত একটি বেস 64-এনকোডারটির একটি জেএস বাস্তবায়ন, যাতে আপনি ডেটা ফেরত পাঠাতে পারেন, আপনি btoaফাংশনটি চেষ্টা করতে পারেন try

b64enc = btoa(uint);

বিটিওএতে কয়েকটি দ্রুত নোট - এটি মানক নয়, তাই ব্রাউজারগুলি এটি সমর্থন করতে বাধ্য হয় না। তবে বেশিরভাগ ব্রাউজারই তা করে। বড়গুলি, অন্তত। atobবিপরীত রূপান্তর হয়।

আপনার যদি অন্য কোনও বাস্তবায়ন প্রয়োজন হয় বা আপনি এমন একটি প্রান্তের সন্ধান পেয়েছেন যেখানে ব্রাউজারটি আপনি কী সম্পর্কে কথা বলছেন সে সম্পর্কে কোনও ধারণা নেই, জেএসের জন্য একটি বেস 64 এনকোডার অনুসন্ধান করা খুব বেশি কঠিন হবে না।

আমি মনে করি যে তাদের মধ্যে 3 টি আমার কোম্পানির ওয়েবসাইটে ঝুলছে, কিছু কারণে ...


ধন্যবাদ, আমি এর আগে চেষ্টা করে দেখিনি।
কায়ো কেটো

10
কয়েক নোট। বিটিওএ এবং অটোব আসলে HTML5 মানককরণ প্রক্রিয়ার অংশ এবং বেশিরভাগ ব্রাউজারগুলি ইতিমধ্যে ইতিমধ্যে একইভাবে তাদের সমর্থন করে mostly দ্বিতীয়ত, btoa এবং atob কেবল স্ট্রিং দিয়ে কাজ করে। Uint8Array এ বিটিওএ চালানো প্রথমে টফ স্ট্রিং () ব্যবহার করে বাফারটিকে স্ট্রিংয়ে রূপান্তরিত করবে। "[অবজেক্ট Uint8Array]" স্ট্রিংয়ের ফলাফল। এটা সম্ভবত উদ্দেশ্য হয় না।
কানাকা

4
@ কায়োকেটো আপনি আপনার নির্বাচিত উত্তর পরিবর্তন করার বিষয়ে বিবেচনা করতে চাইতে পারেন। এই উত্তরটি সঠিক নয়।
কনক

-4

এনপিএম গুগল-ক্লোজার-লাইব্রেরি ইনস্টল করুন - সেভ করুন

require("google-closure-library");
goog.require('goog.crypt.base64');

var result =goog.crypt.base64.encodeByteArray(Uint8Array.of(1,83,27,99,102,66));
console.log(result);

$node index.jsকনসোলে AVMbY2Y = লিখবে ।


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