اختار المؤلف صندوق الإغاثة من فيروس كورونا (كوفيد-19) ليتلقى تبرعًا كجزء من برنامج الكتابة من أجل التبرعات.
المقدمة
A buffer is a space in memory (typically RAM) that stores binary data. In Node.js, we can access these spaces of memory with the built-in Buffer
class. Buffers store a sequence of integers, similar to an array in JavaScript. Unlike arrays, you cannot change the size of a buffer once it is created.
قد تكون قد استخدمت البوافر بشكل ضمني إذا كنت قد كتبت كود Node.js بالفعل. على سبيل المثال، عند قراءة من ملف باستخدام fs.readFile()
، يتم إرجاع البيانات إلى الاستدعاء أو الوعد بشكل كائن بوفر. بالإضافة إلى ذلك، عندما تتم عمليات الطلبات HTTP في Node.js، يتم إرجاع تيارات البيانات التي تُخزن مؤقتًا في بوفر داخلي عندما لا يتمكن العميل من معالجة التيار بالكامل دفعة واحدة.
تكون البوافر مفيدة عند التفاعل مع البيانات الثنائية، عادةً عند مستويات الشبكات الدنيا. كما تجهزك بالقدرة على القيام بعمليات تلاعب دقيقة على البيانات في Node.js.
في هذا البرنامج التعليمي، ستستخدم واجهة إعادة الطباعة القابلة للتشغيل في نود.جي إس لتنفيذ مجموعة متنوعة من الأمثلة على البوافر، مثل إنشاء البوافر، وقراءة من البوافر، والكتابة إلى البوافر ونسخها، واستخدام البوافر لتحويل البيانات بين الثنائية والمشفرة. بحلول نهاية البرنامج التعليمي، ستكون قد تعلمت كيفية استخدام فئة Buffer
للعمل مع البيانات الثنائية.
المتطلبات المسبقة
- ستحتاج إلى تثبيت نود.جي إس على جهاز التطوير الخاص بك. يستخدم هذا البرنامج التعليمي الإصدار 10.19.0. لتثبيت هذا على نظام التشغيل macOS أو Ubuntu 18.04، اتبع الخطوات في كيفية تثبيت نود.جي إس وإنشاء بيئة تطوير محلية على macOS أو قسم التثبيت باستخدام PPA من كيفية تثبيت نود.جي إس على Ubuntu 18.04.
- في هذا البرنامج التعليمي، ستتفاعل مع البوافر في واجهة إعادة الطباعة القابلة للتشغيل في نود.جي إس (REPL). إذا كنت ترغب في معرفة كيفية استخدام واجهة إعادة الطباعة القابلة للتشغيل في نود.جي إس بشكل فعال، يمكنك قراءة دليلنا على كيفية استخدام واجهة إعادة الطباعة القابلة للتشغيل في نود.جي إس.
- لهذا المقال نتوقع أن يكون المستخدم مرتاحًا مع JavaScript الأساسي وأنواع بياناته. يمكنك تعلم تلك الأساسيات مع سلسلة كيفية البرمجة في جافا سكريبت.
الخطوة 1 — إنشاء مخزن
هذه الخطوة الأولى ستعرض لك الطريقتين الأساسيتين لإنشاء كائن مخزن في Node.js.
لتقرر أي الطريقتين تريد استخدامها، تحتاج إلى الإجابة على هذا السؤال: هل تريد إنشاء مخزن جديد أم استخراج مخزن من البيانات الموجودة بالفعل؟ إذا كنت ستخزن البيانات في الذاكرة التي لم تتلقاها بعد، فسترغب في إنشاء مخزن جديد. في Node.js نستخدم وظيفة alloc()
من Buffer
الفئة للقيام بذلك.
دعونا نفتح Node.js REPL لنرى بأنفسنا. في الطرفية الخاصة بك، أدخل الأمر node
:
سوف ترى الرمز يبدأ بـ >
.
تأخذ وظيفة alloc()
حجم المخزن كمعامل أولي ووحيد مطلوب لها. الحجم هو عدد صحيح يمثل عدد البايتات التي ستستخدمها كائن المخزن. على سبيل المثال، إذا أردنا إنشاء مخزن كان حجمه 1 كيلوبايت (KB)، ما يعادل 1024 بايتًا، سندخل هذا في وحدة التحكم:
لإنشاء مخزن جديد، استخدمنا الفئة المتاحة عالميًا Buffer
، التي تحتوي على الطريقة alloc()
. من خلال توفير 1024
كمعامل لـ alloc()
، أنشأنا مخزنًا بحجم 1 كيلوبايت.
بشكل افتراضي، عندما تقوم بتهيئة مخزن باستخدام alloc()
، يتم ملؤه بصفريات ثنائية كبديل للبيانات لاحقًا. ومع ذلك، يمكننا تغيير القيمة الافتراضية إذا أردنا. إذا أردنا إنشاء مخزن جديد بوجود أن 1
بدلاً من 0
، فسنقوم بتعيين المعامل الثاني لدالة alloc()
—fill
.
في نافذة الطرفية الخاصة بك، أنشئ مخزنًا جديدًا عند موجه الـ REPL مملوء بالأن 1
:
لقد أنشأنا مؤخرًا كائن مخزن جديد يشير إلى مساحة في الذاكرة تحتوي على 1 كيلوبايت من الأن 1
s. على الرغم من إدخالنا لعدد صحيح، إلا أن جميع البيانات المخزنة في المخزن هي بيانات ثنائية.
يمكن أن تأتي البيانات الثنائية بتنسيقات مختلفة. على سبيل المثال، دعنا نفكر في تسلسل ثنائي يمثل بايت من البيانات: 01110110
. إذا كان هذا التسلسل الثنائي يمثل سلسلة باللغة الإنجليزية باستخدام معيار الترميز ASCII، فسيكون الحرف v
. ومع ذلك، إذا كان جهاز الكمبيوتر الخاص بنا يعالج صورة، فقد تحتوي هذه التسلسل الثنائي على معلومات حول لون بكسل.
يعرف الكمبيوتر كيفية معالجتها بشكل مختلف لأن البايتات مشفرة بشكل مختلف. ترميز البايت هو تنسيق البايت. يستخدم المخزن المؤقت في Node.js مخطط الترميز UTF-8 افتراضيًا إذا تم تهيئته باستخدام بيانات سلسلة. يمثل بايت في UTF-8 رقمًا، أو حرفًا (باللغة الإنجليزية وباللغات الأخرى)، أو رمزًا. يعتبر UTF-8 فائق المجموعة ل ASCII، الرمز القياسي الأمريكي لتبادل المعلومات. يمكن لـ ASCII ترميز البايتات بالحروف الإنجليزية الكبيرة والصغيرة، والأرقام من 0 إلى 9، وبضعة رموز أخرى مثل علامة التعجب (!) أو علامة الـ ampersand (&).
إذا كنا نكتب برنامجًا يمكن أن يعمل فقط مع أحرف ASCII، يمكننا تغيير الترميز المستخدم بواسطة وظيفة alloc()
التي تستخدمها البايت مع الوسيطة الثالثة – encoding
.
لنقم بإنشاء مخزن مؤقت جديد يكون طوله خمسة بايتات ويخزن فقط الأحرف ASCII:
تم تهيئة المخزن المؤقت بخمسة بايتات من الحرف a
، باستخدام التمثيل الرقمي للـ ASCII.
ملاحظة: بشكل افتراضي، يدعم Node.js الترميزات الأحرفية التالية:
- ASCII، الممثلة بـ
ascii
- UTF-8، الممثلة بـ
utf-8
أوutf8
- UTF-16، الممثلة بـ
utf-16le
أوutf16le
- UCS-2، الممثلة بواسطة
ucs-2
أوucs2
- Base64، الممثلة بواسطة
base64
- Hexadecimal، الممثلة بواسطة
hex
- ISO/IEC 8859-1، الممثلة بواسطة
latin1
أوbinary
يمكن استخدام جميع هذه القيم في وظائف فئة الفهرس التي تقبل معلمة encoding
. لذا، هذه القيم جميعها صالحة لطريقة alloc()
حتى الآن كنا نقوم بإنشاء فهارس جديدة باستخدام وظيفة alloc()
. ولكن في بعض الأحيان قد نرغب في إنشاء فهرس من البيانات الموجودة بالفعل، مثل سلسلة أو مصفوفة
لإنشاء فهرس من البيانات الموجودة مسبقًا، نستخدم الطريقة from()
. يمكننا استخدام تلك الوظيفة لإنشاء فهارس من:
- مصفوفة من الأعداد الصحيحة: قيم الأعداد الصحيحة يمكن أن تكون بين
0
و255
ArrayBuffer
: هذا هو كائن JavaScript الذي يخزن طولًا ثابتًا من البايتات- A string.
- فهرس آخر.
- الكائنات الأخرى في جافا سكريبت التي تحتوي على خاصية
Symbol.toPrimitive
. تلك الخاصية تُخبر جافا سكريبت كيفية تحويل الكائن إلى نوع بيانات أساسي:boolean
،null
،undefined
،number
،string
، أوsymbol
. يمكنك قراءة المزيد عن الرموز في وثائق جافا سكريبت من موزيلا هنا.
لنرى كيف يمكننا إنشاء مخزن مؤقت من سلسلة نصية. في نافذة تعليمات Node.js، أدخل الأمر التالي:
الآن لدينا كائن مخزن مؤقت تم إنشاؤه من السلسلة النصية My name is Paul
. دعنا ننشئ مخزنًا مؤقتًا جديدًا من مخزن مؤقت آخر أنشأناه مسبقًا:
لقد أنشأنا الآن مخزنًا مؤقتًا جديدًا يحتوي على نفس البيانات التي تحتوي عليها asciiBuf
.
الآن بعد أن قمنا بإنشاء مخازن مؤقتة، يمكننا الغوص في أمثلة على قراءة بياناتها.
الخطوة 2 — قراءة من مخزن مؤقت
هناك العديد من الطرق للوصول إلى البيانات في مخزن مؤقت. يمكننا الوصول إلى بايت فردي في مخزن مؤقت أو يمكننا استخراج المحتويات بأكملها.
للوصول إلى بايت واحد من مخزن مؤقت، نمرر الفهرس أو موقع البايت الذي نريده. تقوم المخازن المؤقتة بتخزين البيانات بتسلسل مثل الصفائف. كما أنها تُفهرس بياناتها مثل الصفائف، بدءًا من 0
. يمكننا استخدام تقديم الصفائف على كائن المخزن المؤقت للحصول على بايت فردي.
لنرى كيف يبدو هذا عن طريق إنشاء مخزن مؤقت من سلسلة نصية في REPL:
الآن لنقرأ البايت الأول من المخزن المؤقت:
عند الضغط على ENTER
، سيعرض REPL:
Output72
العدد الصحيح 72
يتوافق مع التمثيل UTF-8 للحرف H
.
ملاحظة: قيم البايتات يمكن أن تكون أرقام بين 0
و 255
. البايت هو تسلسل من 8 بت. البت هو ثنائي، وبالتالي يمكن أن يكون لديه قيمة واحدة فقط من اثنين: 0
أو 1
. إذا كان لدينا تسلسل من 8 بت وقيمتين محتملتين لكل بت، فإننا نمتلك حدًا أقصى يبلغ 2⁸ قيمة محتملة للبايت. يعني هذا وجود حد أقصى لـ 256 قيمة. نظرًا لأننا نبدأ العد من الصفر، فهذا يعني أن أعلى رقم لدينا هو 255.
لنفعل الشيء نفسه للبايت الثاني. أدخل ما يلي في REPL:
يعيد REPL 105
، الذي يمثل الحرف الصغير i
.
وأخيرًا، لنحصل على الحرف الثالث:
سوف ترى 33
معروضًا في REPL، الذي يتوافق مع !
.
لنحاول الحصول على بايت من فهرس غير صالح:
سيعيد REPL:
Outputundefined
هذا تمامًا كما لو حاولنا الوصول إلى عنصر في مصفوفة بفهرس غير صحيح.
الآن بعد أن رأينا كيفية قراءة البايتات الفردية لمخزن مؤقت، لنرى خياراتنا لاسترجاع جميع البيانات المخزنة في مخزن مؤقت مرة واحدة. يأتي كائن المخزن المؤقت مع أساليب toString()
و toJSON()
، والتي تُرجع محتويات المخزن المؤقت بأكملها بتنسيقين مختلفين.
كما يوحي اسمه، تحول الطريقة toString()
بايتات الوسيط إلى سلسلة وتعيدها للمستخدم. إذا استخدمنا هذه الطريقة على hiBuf
، سنحصل على السلسلة Hi!
. لنجرب ذلك!
في البرومبت، أدخل:
سيعيد REPL:
Output'Hi!'
هذا الوسيط تم إنشاؤه من سلسلة. لنرى ماذا يحدث إذا استخدمنا toString()
على وسيط لم يتم إنشاؤه من بيانات نصية.
دعنا ننشئ وسيطًا جديدًا فارغًا بحجم 10
بايتات:
الآن، دعونا نستخدم الطريقة toString()
:
سنرى النتيجة التالية:
'\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'
السلسلة \u0000
هي الحرف اليونيكودي لـ NULL
. يتوافق مع الرقم 0
. عندما لا تتم ترميز بيانات الوسيط كسلسلة، تعيد الطريقة toString()
ترميز UTF-8 للبايتات.
الطريقة toString()
لديها معامل اختياري، encoding
. يمكننا استخدام هذا المعامل لتغيير ترميز بيانات الوسيط المُرجَعة.
على سبيل المثال، إذا كنت ترغب في الحصول على الترميز السداسي عشري لـ hiBuf
، يمكنك إدخال الأمر التالي في البرومبت:
سيقوم هذا البيان بالتقييم إلى:
Output'486921'
486921
هو التمثيل السداسي عشري للبايتات التي تمثل السلسلة Hi!
. في Node.js، عندما يرغب المستخدمون في تحويل ترميز البيانات من شكل إلى آخر، يقومون عادة بوضع السلسلة في وسيط واستدعاء toString()
باستخدام الترميز المطلوب.
تتصرف طريقة toJSON()
بشكل مختلف. بغض النظر عما إذا كان الوسيطة تم إنشاؤها من سلسلة نصية أم لا، فإنها تعيد دائمًا البيانات كالتمثيل العددي للبايت.
لنعيد استخدام الوسائط hiBuf
و tenZeroes
لممارسة استخدام toJSON()
. في سطر الأوامر، أدخل:
سيقوم REPL بإعادة:
Output{ type: 'Buffer', data: [ 72, 105, 33 ] }
تحتوي كائن JSON على خاصية type
التي ستكون دائمًا Buffer
. هذا لكي تتمكن البرامج من التمييز بين هذه الكائنات JSON وغيرها من الكائنات JSON.
تحتوي الخاصية data
على مصفوفة للتمثيل العددي للبايتات. قد لاحظت أن 72
، 105
، و 33
تتوافق مع القيم التي حصلنا عليها عندما استخرجنا البايتات بشكل فردي.
لنجرب الطريقة toJSON()
مع tenZeroes
:
في REPL، سترى الآتي:
Output{ type: 'Buffer', data: [
0, 0, 0, 0, 0,
0, 0, 0, 0, 0
] }
النوع هو نفسه كما هو ملاحظ من قبل. ومع ذلك، فإن البيانات الآن هي مصفوفة تحتوي على عشرة أصفار.
الآن بعد أن غطينا الطرق الرئيسية للقراءة من وسيطة، دعونا نلقي نظرة على كيفية تعديل محتويات الوسيطة.
الخطوة 3 — تعديل وسيطة
هناك العديد من الطرق التي يمكننا استخدامها لتعديل كائن وسيطة موجود. على غرار القراءة، يمكننا تعديل بايتات الوسيطة بشكل فردي باستخدام بنية المصفوفة. يمكننا أيضًا كتابة محتويات جديدة إلى وسيطة، لاستبدال البيانات الموجودة.
لنبدأ بالنظر في كيفية تغيير البايتات الفردية في مخزن. يُذكر متغير المخزن الخاص بنا hiBuf
، الذي يحتوي على السلسلة Hi!
. لنقم بتغيير كل بايت بحيث يحتوي بدلاً من ذلك على Hey
.
في REPL، لنحاول أولاً تعيين العنصر الثاني من hiBuf
إلى e
:
الآن، لنرى هذا المخزن كسلسلة للتأكد من أنه يخزن البيانات الصحيحة. نتابع باستدعاء طريقة toString()
:
سيتم تقييمها كالتالي:
Output'H\u0000!'
لقد حصلنا على هذا الإخراج الغريب لأن المخزن يمكن أن يقبل قيمة عددية فقط. لا يمكننا تعيينه على الحرف e
؛ بل يجب علينا تعيينه بالعدد الذي تمثله النسخة الثنائية لـ e
:
الآن عندما نستدعي طريقة toString()
:
نحصل على هذا الإخراج في REPL:
Output'He!'
لتغيير الحرف الأخير في المخزن، نحتاج إلى تعيين العنصر الثالث إلى العدد الذي يتوافق مع البايت لـ y
:
لنتأكد باستخدام طريقة toString()
مرة أخرى:
سيعرض REPL الخاص بك:
Output'Hey'
إذا حاولنا كتابة بايت خارج نطاق المخزن، سيتم تجاهله ولن تتغير محتويات المخزن. على سبيل المثال، لنحاول تعيين العنصر الرابع غير الموجود من المخزن إلى o
:
يمكننا التأكد من أن المخزن لم يتغير باستخدام طريقة toString()
:
الإخراج لا يزال:
Output'Hey'
إذا أردنا تغيير محتويات البوفر بأكمله، يمكننا استخدام طريقة write()
. تقبل طريقة write()
سلسلة نصية ستستبدل محتويات البوفر.
لنستخدم طريقة write()
لتغيير محتويات hiBuf
إلى Hi!
. في واجهة تحكم Node.js الخاصة بك، اكتب الأمر التالي:
طريقة write()
أرجعت 3
في REPL. هذا لأنها كتبت ثلاث بايتات من البيانات. كل حرف له بايت واحد في الحجم، لأن هذا البوفر يستخدم ترميز UTF-8، الذي يستخدم بايتًا لكل حرف. إذا كان البوفر يستخدم ترميز UTF-16، الذي يتطلب الحد الأدنى من بايتين لكل حرف، فإن الدالة write()
كانت قد أرجعت 6
.
الآن تأكد من محتويات البوفر باستخدام toString()
:
سيقوم REPL بإنتاج:
Output'Hi!'
هذا أسرع من الحاجة إلى تغيير كل عنصر بايت ببايت.
إذا حاولت كتابة بايتات أكثر من حجم البوفر، سيقبل كائن البوفر فقط البايتات التي تناسب. لتوضيح ذلك، دعنا ننشئ بوفرًا يخزن ثلاث بايتات:
الآن دعنا نحاول كتابة Cats
إليه:
عند تقييم الاستدعاء write()
، يرجع REPL 3
مشيرًا إلى أنه تمت كتابة ثلاث بايتات فقط إلى البوفر. الآن قم بتأكيد أن البوفر يحتوي على البايتات الثلاثة الأولى:
يعيد REPL:
Output'Cat'
تضيف الدالة write()
البايتات بترتيب تسلسلي، لذا لم يتم وضع البايتات الثلاثة الأولى في البوفر فقط.
بدلاً من ذلك، دعنا ننشئ Buffer
يخزن أربع بايتات:
اكتب نفس المحتوى عليه:
ثم أضف بعض المحتوى الجديد الذي يحتل مساحة أقل من المحتوى الأصلي:
نظرًا لأن البافر يكتب بشكل تسلسلي، بدءًا من 0
، إذا قمنا بطباعة محتويات البافر:
سنجد:
Output'Hits'
الحروف الأولى تمت الكتابة فوقها، لكن بقية البافر لم يتم لمسته.
أحيانًا، البيانات التي نريدها في البافر السابقة لدينا ليست في سلسلة ولكنها موجودة في كائن بافر آخر. في هذه الحالات، يمكننا استخدام الدالة copy()
لتعديل ما يخزنه البافر لدينا.
لننشئ بافرين جديدين:
البافرات wordsBuf
و catchphraseBuf
تحتويان على بيانات السلسلة. نريد تعديل catchphraseBuf
بحيث يخزن Nananana Turtle!
بدلاً من Not sure Turtle!
. سنستخدم copy()
للحصول على Nananana
من wordsBuf
إلى catchphraseBuf
.
لننسخ البيانات من بافر واحد إلى الآخر، سنستخدم الطريقة copy()
على البافر الذي هو مصدر المعلومات. لذلك، نظرًا لأن wordsBuf
يحتوي على بيانات السلسلة التي نريد نسخها، نحتاج للنسخ بهذه الطريقة:
المعلمة target
في هذه الحالة هي البافر catchphraseBuf
.
عند إدخال ذلك في REPL، يُرجع 15
مما يشير إلى أنه تم كتابة 15 بايتًا. السلسلة Nananana
تستخدم فقط 8 بايتات من البيانات، لذلك نعلم فورًا أن نسختنا لم تكن كما هو المقصود. استخدم الطريقة toString()
لرؤية محتويات catchphraseBuf
:
تُرجع REPL:
Output'Banana Nananana!'
بشكل افتراضي، قامت copy()
بأخذ محتويات كاملة من wordsBuf
ووضعتها في catchphraseBuf
. نحتاج إلى أن نكون أكثر انتقائية لهدفنا وننسخ فقط Nananana
. دعونا نعيد كتابة المحتويات الأصلية لـ catchphraseBuf
قبل المتابعة:
وظيفة copy()
لديها عدة معلمات أخرى تسمح لنا بتخصيص البيانات التي يتم نسخها إلى النطاق الآخر. إليك قائمة بجميع المعلمات لهذه الوظيفة:
target
– هذه هي المعلمة الوحيدة المطلوبة لـcopy()
. كما رأينا من استخدامنا السابق، فهي الوسيطة التي نريد نسخ إليها.targetStart
– هذا هو فهرس البايتات في الوسيطة الهدف التي يجب أن نبدأ النسخ إليها. بشكل افتراضي هو0
، مما يعني أنه ينسخ البيانات بدءًا من بداية الوسيطة.sourceStart
– هذا هو فهرس البايتات في الوسيطة المصدر التي يجب أن نبدأ النسخ منها.sourceEnd
– هذا هو فهرس البايتات في الوسيطة المصدر التي يجب أن نتوقف عن النسخ عندها. بشكل افتراضي، هو طول الوسيطة.
لنقوم بنسخ Nananana
من wordsBuf
إلى catchphraseBuf
، الهدف target
يجب أن يكون catchphraseBuf
كما كان سابقًا. targetStart
يجب أن يكون 0
حيث نريد ظهور Nananana
في بداية catchphraseBuf
. sourceStart
يجب أن يكون 7
لأن هذا هو المؤشر الذي يبدأ منه Nananana
في wordsBuf
. sourceEnd
يجب أن يستمر كطول للمخازن.
في موجه REPL، قم بنسخ محتويات wordsBuf
مثل هذا:
يؤكد موجه REPL أن 8
بايتات قد تمت كتابتها. لاحظ كيف يُستخدم wordsBuf.length
كقيمة لمعلمة sourceEnd
. مثل الصفوف، تمنحنا خاصية length
حجم المخزن.
الآن دعونا نرى محتويات catchphraseBuf
:
يُعيد موجه REPL:
Output'Nananana Turtle!'
نجاح! تمكنا من تعديل بيانات catchphraseBuf
عن طريق نسخ محتويات wordsBuf
.
يمكنك الخروج من موجه Node.js REPL إذا كنت ترغب في ذلك. لاحظ أن جميع المتغيرات التي تم إنشاؤها لن تكون متاحة بعد الخروج:
الاستنتاج
في هذا البرنامج التعليمي، تعلمت أن البوافر هي تخصيصات ذات طول ثابت في الذاكرة تخزن البيانات الثنائية. أنشأت البوافر أولاً عن طريق تعريف حجمها في الذاكرة وبتهيئتها بالبيانات الموجودة مسبقًا. ثم قرأت البيانات من البوافر عن طريق فحص بايتاتها الفردية واستخدام طرق toString()
و toJSON()
. وأخيرًا، قمت بتعديل البيانات المخزنة بواسطة البوافر عن طريق تغيير بايتاتها الفردية واستخدام الطرق write()
و copy()
.
تمنحك البوافر رؤية رائعة حول كيفية تلاعب البيانات الثنائية بواسطة Node.js. الآن بما أنك تستطيع التفاعل مع البوافر، يمكنك مراقبة الطرق المختلفة التي يؤثر بها ترميز الحروف على كيفية تخزين البيانات. على سبيل المثال، يمكنك إنشاء بوافر من بيانات سلسلة ليست من ترميز UTF-8 أو ASCII ومراقبة الفرق في الحجم. يمكنك أيضًا أخذ بوافر بترميز UTF-8 واستخدام toString()
لتحويلها إلى مخططات ترميز أخرى.
للتعرف على البوافر في Node.js، يمكنك قراءة وثائق Node.js عن كائن Buffer
. إذا كنت ترغب في مواصلة تعلم Node.js، يمكنك العودة إلى سلسلة كيفية البرمجة في Node.js، أو تصفح مشاريع البرمجة والإعدادات على صفحة موضوعنا حول Node.
Source:
https://www.digitalocean.com/community/tutorials/using-buffers-in-node-js