Buffer در Node.js: متدهای نوشتن داده‌ها

کلاس Buffer در Node.js مجموعه‌ای از متدها برای نوشتن انواع داده‌ها در حافظهٔ باینری ارائه می‌دهد. این متدها شامل نوشتن اعداد صحیح signed و unsigned، اعداد اعشاری، مقادیر بزرگ (bigint) و رشته‌ها هستند. همچنین امکان نوشتن داده‌ها در قالب big-endian یا little-endian وجود دارد. این قابلیت‌ها برای پردازش فایل‌های باینری، پروتکل‌های شبکه و مدیریت داده‌های سطح پایین حیاتی‌اند.

buf.writeBigUInt64BE / buf.writeBigUInt64LEbuf.writeDoubleBE / buf.writeDoubleLEbuf.writeFloatBE / buf.writeFloatLEbuf.writeIntBE / buf.writeIntLEbuf.writeUIntBE / buf.writeUIntLE

~6 دقیقه مطالعه · آخرین به‌روزرسانی ۵ دی ۱۴۰۴

1. نوشتن BigUInt64


  • buf.writeBigUInt64BE(value, offset): نوشتن عدد bigint به‌صورت unsigned ۶۴ بیتی big-endian.
  • buf.writeBigUInt64LE(value, offset): نوشتن عدد bigint به‌صورت unsigned ۶۴ بیتی little-endian.
const buf = Buffer.allocUnsafe(8);
buf.writeBigUInt64BE(0xdecafafecacefaden, 0);
console.log(buf); // 

2. نوشتن Double و Float


  • buf.writeDoubleBE(value, offset): نوشتن عدد اعشاری ۶۴ بیتی big-endian.
  • buf.writeDoubleLE(value, offset): نوشتن عدد اعشاری ۶۴ بیتی little-endian.
  • buf.writeFloatBE(value, offset): نوشتن عدد اعشاری ۳۲ بیتی big-endian.
  • buf.writeFloatLE(value, offset): نوشتن عدد اعشاری ۳۲ بیتی little-endian.
const buf = Buffer.allocUnsafe(8);
buf.writeDoubleBE(123.456, 0);
console.log(buf);

3. نوشتن اعداد صحیح کوچک


  • buf.writeInt8(value, offset): نوشتن عدد signed ۸ بیتی.
  • buf.writeUInt8(value, offset): نوشتن عدد unsigned ۸ بیتی.
const buf = Buffer.allocUnsafe(2);
buf.writeInt8(2, 0);
buf.writeInt8(-2, 1);
console.log(buf); // 

4. نوشتن Int16 و UInt16


  • buf.writeInt16BE(value, offset): نوشتن عدد signed ۱۶ بیتی big-endian.
  • buf.writeInt16LE(value, offset): نوشتن عدد signed ۱۶ بیتی little-endian.
  • buf.writeUInt16BE(value, offset): نوشتن عدد unsigned ۱۶ بیتی big-endian.
  • buf.writeUInt16LE(value, offset): نوشتن عدد unsigned ۱۶ بیتی little-endian.

5. نوشتن Int32 و UInt32


  • buf.writeInt32BE(value, offset): نوشتن عدد signed ۳۲ بیتی big-endian.
  • buf.writeInt32LE(value, offset): نوشتن عدد signed ۳۲ بیتی little-endian.
  • buf.writeUInt32BE(value, offset): نوشتن عدد unsigned ۳۲ بیتی big-endian.
  • buf.writeUInt32LE(value, offset): نوشتن عدد unsigned ۳۲ بیتی little-endian.

6. نوشتن IntBE / IntLE و UIntBE / UIntLE


نوشتن اعداد صحیح با طول دلخواه (۱ تا ۶ بایت) به‌صورت big-endian یا little-endian.

const buf = Buffer.allocUnsafe(6);
buf.writeIntBE(0x1234567890ab, 0, 6);
console.log(buf); // 

7. نوشتن رشته‌ها


buf.write(string[, offset[, length]][, encoding]): نوشتن رشته در Buffer با encoding مشخص (پیش‌فرض UTF-8).

const buf = Buffer.alloc(256);
const len = buf.write('½ + ¼ = ¾', 0);
console.log(`${len} bytes: ${buf.toString('utf8',0,len)}`);

نتیجه‌گیری


متدهای نوشتن در کلاس Buffer امکان ذخیرهٔ داده‌های باینری در قالب‌های مختلف را فراهم می‌کنند. با پشتیبانی از انواع signed و unsigned، و ترتیب‌های big-endian و little-endian، این متدها برای پردازش داده‌های سطح پایین در Node.js بسیار حیاتی هستند.

1. مدیریت آرگومان‌های تابع


Addonها معمولاً توابعی را به جاوااسکریپت صادر می‌کنند. برای مدیریت آرگومان‌ها باید تعداد و نوع آن‌ها بررسی شود.

// addon.cc
void Add(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();

  if (args.Length() < 2) {
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate,"Wrong number of arguments").ToLocalChecked()));
    return;
  }

  if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
    isolate->ThrowException(Exception::TypeError(
        String::NewFromUtf8(isolate,"Wrong arguments").ToLocalChecked()));
    return;
  }

  double value = args[0].As()->Value() + args[1].As()->Value();
  Local num = Number::New(isolate, value);
  args.GetReturnValue().Set(num);
}

این تابع دو عدد را جمع کرده و نتیجه را به جاوااسکریپت بازمی‌گرداند.

2. اجرای کال‌بک‌ها


Addonها می‌توانند توابع جاوااسکریپت را به‌عنوان آرگومان دریافت کرده و آن‌ها را در C++ اجرا کنند.

// addon.cc
void RunCallback(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  Local context = isolate->GetCurrentContext();
  Local cb = Local::Cast(args[0]);
  const unsigned argc = 1;
  Local argv[argc] = {
      String::NewFromUtf8(isolate,"hello world").ToLocalChecked() };
  cb->Call(context, Null(isolate), argc, argv).ToLocalChecked();
}

در این مثال، کال‌بک به‌صورت همزمان اجرا شده و رشتهٔ "hello world" را چاپ می‌کند.

3. ساخت اشیاء (Object Factory)


Addonها می‌توانند اشیاء جدید ایجاد کرده و آن‌ها را به جاوااسکریپت بازگردانند.

// addon.cc
void CreateObject(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  Local context = isolate->GetCurrentContext();

  Local obj = Object::New(isolate);
  obj->Set(context,
           String::NewFromUtf8(isolate,"msg").ToLocalChecked(),
           args[0]->ToString(context).ToLocalChecked()).FromJust();

  args.GetReturnValue().Set(obj);
}


این تابع یک شیء با ویژگی msg ایجاد می‌کند که مقدار آن برابر با رشتهٔ ورودی است.

نتیجه‌گیری


Addonها در Node.js ابزاری قدرتمند برای توسعه‌دهندگان هستند تا بتوانند قابلیت‌های سطح پایین را به جاوااسکریپت بیاورند. مدیریت صحیح آرگومان‌ها، اجرای کال‌بک‌ها و ساخت اشیاء از جمله تکنیک‌های کلیدی در توسعهٔ این ماژول‌هاست.

1. Function Factory


در این الگو، یک تابع جاوااسکریپت ساخته می‌شود که به یک تابع C++ متصل است و سپس به جاوااسکریپت بازگردانده می‌شود.

// addon.cc
void MyFunction(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world").ToLocalChecked());
}

void CreateFunction(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  Local context = isolate->GetCurrentContext();
  Local tpl = FunctionTemplate::New(isolate, MyFunction);
  Local fn = tpl->GetFunction(context).ToLocalChecked();
  fn->SetName(String::NewFromUtf8(isolate, "theFunction").ToLocalChecked());
  args.GetReturnValue().Set(fn);
}

این کد یک تابع جاوااسکریپت ایجاد می‌کند که هنگام اجرا رشتهٔ "hello world" را بازمی‌گرداند.

2. Wrap کردن اشیاء C++


با استفاده از کلاس node::ObjectWrap می‌توان کلاس‌های C++ را به‌گونه‌ای بسته‌بندی کرد که با new در جاوااسکریپت نمونه‌سازی شوند.

// myobject.h
class MyObject : public node::ObjectWrap {
 public:
  static void Init(v8::Local exports);
 private:
  explicit MyObject(double value = 0);
  ~MyObject();
  static void New(const v8::FunctionCallbackInfo& args);
  static void PlusOne(const v8::FunctionCallbackInfo& args);
  double value_;
};

در فایل myobject.cc متدها پیاده‌سازی می‌شوند و به prototype اضافه می‌گردند:

NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);

این متد مقدار داخلی شیء را یک واحد افزایش می‌دهد.

3. Factory برای اشیاء بسته‌بندی‌شده


به‌جای استفادهٔ مستقیم از new در جاوااسکریپت، می‌توان یک متد factory در C++ نوشت که نمونهٔ جدید ایجاد کند:

// addon.cc
void CreateObject(const FunctionCallbackInfo& args) {
  MyObject::NewInstance(args);
}

این الگو امکان ایجاد اشیاء را بدون نیاز به new در جاوااسکریپت فراهم می‌کند.

نتیجه‌گیری


الگوهای Function Factory و ObjectWrap ابزارهای قدرتمندی برای توسعهٔ Addonها در Node.js هستند. با استفاده از این الگوها می‌توان توابع و اشیاء C++ را به‌طور مستقیم در جاوااسکریپت در دسترس قرار داد و از قابلیت‌های سطح پایین در برنامه‌های Node.js بهره برد.

1. ایجاد و پاس دادن اشیاء


ابتدا یک تابع createObject برای ساخت نمونهٔ جدید از کلاس C++ ایجاد می‌شود. سپس تابع add دو شیء از نوع MyObject را دریافت کرده و مقادیر داخلی آن‌ها را جمع می‌کند.

// addon.cc
void Add(const FunctionCallbackInfo& args) {
  Isolate* isolate = args.GetIsolate();
  Local context = isolate->GetCurrentContext();

  MyObject* obj1 = node::ObjectWrap::Unwrap(
      args[0]->ToObject(context).ToLocalChecked());
  MyObject* obj2 = node::ObjectWrap::Unwrap(
      args[1]->ToObject(context).ToLocalChecked());

  double sum = obj1->value() + obj2->value();
  args.GetReturnValue().Set(Number::New(isolate, sum));
}

2. دسترسی به مقادیر داخلی


برای دسترسی به مقدار خصوصی value_ در کلاس MyObject، یک متد عمومی value() اضافه می‌شود:

// myobject.h
inline double value() const { return value_; }

3. پیاده‌سازی کلاس MyObject


کلاس MyObject مشابه نسخه‌های قبلی پیاده‌سازی می‌شود، با این تفاوت که اکنون می‌توان نمونه‌ها را unwrap کرده و مقادیرشان را در توابع دیگر استفاده کرد.

MyObject::MyObject(double value) : value_(value) {}
void MyObject::NewInstance(const FunctionCallbackInfo& args) {
  // ایجاد نمونه جدید و بازگرداندن آن
}

4. تست در جاوااسکریپت


پس از کامپایل Addon، می‌توان اشیاء را ایجاد و بین توابع پاس داد:

// test.js
const addon = require('./build/Release/addon');

const obj1 = addon.createObject(10);
const obj2 = addon.createObject(20);
const result = addon.add(obj1, obj2);

console.log(result); // 30

نتیجه‌گیری


با استفاده از ObjectWrap::Unwrap می‌توان اشیاء بسته‌بندی‌شدهٔ C++ را در جاوااسکریپت پاس داد و در توابع مختلف استفاده کرد. این تکنیک امکان تعامل پیشرفته بین کد بومی و جاوااسکریپت را فراهم کرده و برای توسعهٔ Addonهای پیچیده در Node.js بسیار حیاتی است.

نوشته و پژوهش‌شده توسط دکتر شاهین صیامی

مقالات مرتبط

آشنایی کامل با ماژول Cluster در Node.js و نحوه افزایش مقیاس‌پذیری سرور

ماژول Cluster در Node.js به توسعه‌دهندگان اجازه می‌دهد چندین پردازش همزمان ایجاد کنند که یک پورت سرور را به اشتراک می‌گذارند. این کار باعث استفاده بهتر از هسته‌های CPU و افزایش توان پردازش برنامه می‌شود. در این مقاله نحوه کار Cluster، مدیریت Workerها، تنظیمات مهم و مثال عملی را بررسی می‌کنیم.

ادامه

راهنمای جامع ماژول VM در Node.js (ماژول node:vm)

ماژول node:vm امکان کامپایل و اجرای کد جاوااسکریپت در کانتکست‌های ایزولهٔ V8 را فراهم می‌کند. این کانتکست‌ها مانند یک «سندباکس سبک» داخل برنامهٔ Node.js عمل می‌کنند و هرکدام globalThis مخصوص خود را دارند. این ماژول برای اجرای پویا، موتورهای قالب (Template Engines)، سیستم‌های افزونه (Plugin Systems)، REPLها و تست ایزولهٔ منطق بسیار مناسب است. اما نکتهٔ بسیار مهم: vm یک ابزار امنیتی نیست و نباید برای اجرای کدهای غیرقابل‌اعتماد استفاده شود.

ادامه

راهنمای جامع ماژول V8 در Node.js (ماژول node:v8)

راهنمای جامع ماژول V8 در Node.js (ماژول node:v8)

ادامه

راهنمای جامع Worker Threads در Node.js (ماژول node:worker_threads)

ماژول node:worker_threads امکان اجرای واقعی چندریسمانی (Multithreading) را در Node.js فراهم می‌کند. برخلاف مدل تک‌ریسمانی سنتی Node.js، Worker Threads اجازه می‌دهند کارهای سنگین CPU در ریسه‌های جداگانه اجرا شوند بدون اینکه حلقهٔ رویداد (Event Loop) مسدود شود. این ماژول از حافظهٔ اشتراکی، انتقال بدون کپی (Zero‑Copy)، کانال‌های پیام، Worker Pool، محدودیت منابع و ابزارهای همگام‌سازی پیشرفته پشتیبانی می‌کند. Worker Threads برای پردازش‌های محاسباتی سنگین ایده‌آل هستند، در حالی که I/O همچنان باید توسط ریسهٔ اصلی مدیریت شود.

ادامه

راهنمای جامع ماژول util در Node.js

ماژول node:util مجموعه‌ای از توابع کمکی قدرتمند برای استفاده در هستهٔ Node.js و همچنین توسعهٔ برنامه‌ها ارائه می‌دهد. این ماژول ابزارهایی برای دیباگ، بازرسی اشیا، تبدیل Callback ↔ Promise، قالب‌بندی رشته‌ها، بررسی انواع، مدیریت خطاها، رمزگذاری متن، پردازش MIME، پارس آرگومان‌های CLI، سیگنال‌های Abort، و ابزارهای متفرقه فراهم می‌کند. این ماژول یکی از جعبه‌ابزارهای اصلی و ضروری برای توسعه‌دهندگان Node.js است.

ادامه

راهنمای جامع ماژول URL در Node.js

ماژول node:url ابزارهایی برای تحلیل، ساخت، و دست‌کاری URLها در Node.js فراهم می‌کند. Node.js دو API برای کار با URL دارد: WHATWG URL API — استاندارد مدرن و سازگار با مرورگرها (توصیه‌شده). Legacy API — API قدیمی Node.js (غیرتوصیه‌شده). WHATWG URL API یک رابط تمیز، سازگار و قدرتمند برای کار با اجزای URL، پارامترهای query، الگوهای URL و حتی Blob URLها ارائه می‌دهد.

ادامه