WriteStream ma’lumotnomasi


ULASHISH

WriteStream obyekti

WriteStream ma’lumotlarni manzilga yozish imkonini beruvchi oqimdir. Node.js turli holatlar uchun WriteStream implementatsiyalarini taqdim etadi, masalan, fayllarga (fs.WriteStream) yoki standart chiqishga (process.stdout) yozish uchun.

WriteStream’lar stream.Writable interfeysini amalga oshiradi, ya’ni ular ma’lumotlarni asinxron tarzda yozish va backpressure’ni boshqarish uchun metodlar va hodisalarni taqdim etadi.

Umumiy WriteStream turlari

  • fs.WriteStream - fayllarga yozish uchun
  • process.stdout va process.stderr - standart chiqish va xatoga yozish uchun
  • net.Socket (yozishda) - Tarmoq ulanishlariga yozish uchun
  • http.ServerResponse - HTTP javoblarini yozish uchun

WriteStream xususiyatlari

Quyida Node.js WriteStream obyektlarida mavjud bo‘lgan xususiyatlar, asosan, fs.WriteStream amalga oshirilishiga asoslangan:

Xususiyat Tavsif
writeStream.bytesWritten Hozirgacha yozilgan baytlar soni.
writeStream.path Ushbu WriteStream yozayotgan fayl yo‘li (faqat fs.WriteStream uchun).
writeStream.pending Agar true bo‘lsa, asosiy fayl hali ochilmagan.
writeStream.writableHighWaterMark Ushbu WriteStream uchun highWaterMark qiymatini qaytaradi.
writeStream.writableLength Yozish navbatida yozilishga tayyor turgan baytlar (yoki obyektlar) sonini qaytaradi.
writeStream.writableEnded end() chaqirilgandan keyin true bo‘ladi.
writeStream.writableFinished 'finish' hodisasi ishga tushgandan keyin true bo‘ladi.
writeStream.writableObjectMode WriteStream obyekt rejimida yoki yo‘qligini ko‘rsatadi.
writeStream.destroyed Stream yo‘q qilinganligini ko‘rsatadi.


WriteStream metodlari

WriteStream obyektlarida mavjud bo‘lgan eng muhim metodlar:

Metod Tavsif
writeStream.write(chunk[, encoding][, callback]) Oqimga chunk yozadi. Agar ma’lumotlar to‘liq qayta ishlangan bo‘lsa true yoki buferlangan bo‘lsa false qaytaradi. callback ma’lumot bo‘lagi (chunk) to‘liq yuborilganda (flush) chaqiriladi.
writeStream.end([chunk][, encoding][, callback]) WriteStream-ga boshqa ma’lumotlar yozilmasligi haqida signal. Agar chunk berilgan bo‘lsa, u writeStream.write(chunk, encoding) ga, keyin esa writeStream.end(callback) ga ekvivalent bo‘ladi.
writeStream.cork() Barcha yozma ma’lumotlarni xotirada buferlashga majbur qiladi, ular uncork() yoki end() chaqirilganda tozalanadi.
writeStream.uncork() cork() chaqirilgandan beri buferlangan barcha ma’lumotlarni darhol yuboradi (flush).
writeStream.destroy([error]) Oqimni yo‘q qiladi va ixtiyoriy ravishda xato hodisasini chiqaradi. Bu chaqiruvdan keyin WriteStream’dan endi foydalanib bo‘lmaydi.
writeStream.setDefaultEncoding(encoding) Oqimga yozilgan stringlar uchun standart kodlashni o‘rnatadi.

WriteStream hodisalari

WriteStream obyektlari quyidagi hodisalarni chiqaradi:

Hodisa Tavsif
'close' Stream va uning har qanday asosiy manbalari yopilganda chiqariladi.
'drain' Yozish buferi bo‘sh bo‘lganda va qayta yozish xavfsiz bo‘lganda chiqariladi. Bu write() false qaytarganda oqimni boshqarish uchun ishlatiladi.
'error' Yozish vaqtida xato yuz bersa, ishga tushadi.
'finish' end() chaqirilgandan va barcha ma’lumotlar qayta ishlanganidan keyin chiqariladi.
'open' Asosiy resurs (masalan, fayl deskriptori) ochilganda ishga tushadi (fs.WriteStream uchun xos).
'pipe' ReadStream’da pipe() metodi chaqirilganda chiqariladi va bu WriteStreamni maqsad qilib qo‘shadi.
'unpipe' unpipe() metodi ilgari ushbu WriteStreamga uzatilgan ReadStreamda chaqirilganda chiqariladi.
'ready' Stream foydalanishga tayyor bo‘lganda chiqariladi.

Faylga yozish

Ushbu misol WriteStream faylini qanday yaratish va unga ma’lumotlarni yozishni ko‘rsatadi:

const fs = require('fs');
const path = require('path');

// Define the output file path
const outputFile = path.join(__dirname, 'writestream-example.txt');

// Create a WriteStream to write to the file
const writeStream = fs.createWriteStream(outputFile, {
  // Options
  flags: 'w',          // 'w' for write (overwrites existing file)
  encoding: 'utf8',    // Set the encoding for strings
  mode: 0o666,         // File mode (permissions)
  autoClose: true      // Automatically close the file descriptor when the stream ends
});

console.log('File WriteStream properties:');
console.log(`- Path: ${writeStream.path}`);
console.log(`- Pending: ${writeStream.pending}`);
console.log(`- High Water Mark: ${writeStream.writableHighWaterMark} bytes`);

// Handle stream events
writeStream.on('open', (fd) => {
  console.log(`File opened with descriptor: ${fd}`);
});

writeStream.on('ready', () => {
  console.log('WriteStream is ready');
  
  // Write data to the stream
  writeStream.write('Hello, this is the first line.\n');
  writeStream.write('This is the second line.\n');
  writeStream.write('And this is the third line.\n');
  
  // End the stream after writing all data
  writeStream.end('This is the final line.\n', () => {
    console.log('Finished writing to the file');
    console.log(`Total bytes written: ${writeStream.bytesWritten}`);
  });
});

// Handle drain event (when buffer is empty)
writeStream.on('drain', () => {
  console.log('Write buffer drained');
});

// Handle finish event (after end() and all data is flushed)
writeStream.on('finish', () => {
  console.log('All writes have been completed');
  
  // Read back the file contents to verify
  fs.readFile(outputFile, 'utf8', (err, data) => {
    if (err) {
      console.error(`Error reading file: ${err.message}`);
      return;
    }
    
    console.log('\nFile content:');
    console.log('-'.repeat(20));
    console.log(data);
    console.log('-'.repeat(20));
    
    // Clean up the sample file
    fs.unlink(outputFile, (err) => {
      if (err) {
        console.error(`Error removing file: ${err.message}`);
        return;
      }
      console.log('Sample file removed');
    });
  });
});

writeStream.on('close', () => {
  console.log('Stream closed');
});

writeStream.on('error', (err) => {
  console.error(`Error: ${err.message}`);
});
Misolni ishga tushirish »

Orqa bosim bilan ishlash

Ushbu misol katta hajmdagi ma’lumotlarni yozishda teskari bosimni qanday boshqarishni ko‘rsatadi:

const fs = require('fs');
const path = require('path');

// Define the output file path
const backpressureFile = path.join(__dirname, 'backpressure-example.txt');

// Create a WriteStream with a small highWaterMark to demonstrate backpressure
const writeStream = fs.createWriteStream(backpressureFile, {
  highWaterMark: 1024 // 1KB buffer (small to demonstrate backpressure)
});

// Counter for how many chunks we've written
let chunksWritten = 0;
let drainEvents = 0;

// Function to write data until backpressure occurs
function writeChunks() {
  console.log('Writing chunks...');
  
  // Create a large chunk of data
  const chunk = 'a'.repeat(256); // 256 bytes per chunk
  
  // Try to write many chunks
  let canContinue = true;
  
  while (canContinue && chunksWritten < 100) {
    // Attempt to write the chunk
    canContinue = writeStream.write(`Chunk ${chunksWritten}: ${chunk}\n`);
    chunksWritten++;
    
    if (chunksWritten % 10 === 0) {
      console.log(`Wrote ${chunksWritten} chunks so far`);
    }
    
    // If canContinue is false, we hit backpressure
    if (!canContinue) {
      console.log(`Backpressure hit after ${chunksWritten} chunks. Waiting for drain...`);
      
      // Wait for the drain event before continuing
      writeStream.once('drain', () => {
        drainEvents++;
        console.log(`Drain event #${drainEvents} occurred. Resuming writes...`);
        writeChunks(); // Continue writing
      });
    }
  }
  
  // If we've written all chunks, end the stream
  if (chunksWritten >= 100) {
    writeStream.end('\nAll chunks have been written.\n', () => {
      console.log('Ended the WriteStream after writing all chunks');
    });
  }
}

// Start writing chunks when the stream is ready
writeStream.on('ready', () => {
  console.log('WriteStream is ready with highWaterMark =',
    writeStream.writableHighWaterMark, 'bytes');
  
  // Start writing chunks
  writeChunks();
});

// Handle finish event
writeStream.on('finish', () => {
  console.log('\nWrite operation completed');
  console.log(`Total chunks written: ${chunksWritten}`);
  console.log(`Total drain events: ${drainEvents}`);
  console.log(`Total bytes written: ${writeStream.bytesWritten}`);
  
  // Clean up the sample file
  fs.unlink(backpressureFile, (err) => {
    if (err) {
      console.error(`Error removing file: ${err.message}`);
      return;
    }
    console.log('Sample file removed');
  });
});

// Handle errors
writeStream.on('error', (err) => {
  console.error(`Error: ${err.message}`);
});
Misolni ishga tushirish »

cork() va uncork() metodlaridan foydalanish

Bu misol birgalikda yozish uchun cork() va uncork() dan foydalanishni ko‘rsatadi:

const fs = require('fs');
const path = require('path');

// Define the output file paths
const uncorkedFile = path.join(__dirname, 'uncorked-example.txt');
const corkedFile = path.join(__dirname, 'corked-example.txt');

// Function to run the demonstration
function demonstrateCorkUncork() {
  console.log('Demonstrating cork() and uncork() methods');
  
  // 1. Write without corking
  const uncorkedStream = fs.createWriteStream(uncorkedFile);
  
  uncorkedStream.on('finish', () => {
    console.log(`Uncorked stream finished. Bytes written: ${uncorkedStream.bytesWritten}`);
    
    // 2. Now write with corking
    const corkedStream = fs.createWriteStream(corkedFile);
    
    corkedStream.on('finish', () => {
      console.log(`Corked stream finished. Bytes written: ${corkedStream.bytesWritten}`);
      
      // Compare files
      fs.readFile(uncorkedFile, 'utf8', (err, uncorkedData) => {
        if (err) {
          console.error(`Error reading uncorked file: ${err.message}`);
          return;
        }
        
        fs.readFile(corkedFile, 'utf8', (err, corkedData) => {
          if (err) {
            console.error(`Error reading corked file: ${err.message}`);
            return;
          }
          
          console.log('\nFile comparison:');
          console.log(`- Uncorked file size: ${uncorkedData.length} bytes`);
          console.log(`- Corked file size: ${corkedData.length} bytes`);
          console.log(`- Content identical: ${uncorkedData === corkedData}`);
          
          // Clean up sample files
          fs.unlinkSync(uncorkedFile);
          fs.unlinkSync(corkedFile);
          console.log('Sample files removed');
        });
      });
    });
    
    // Start cork operation
    console.log('Writing with cork()...');
    corkedStream.cork();
    
    // Write multiple chunks of data
    for (let i = 0; i < 1000; i++) {
      corkedStream.write(`Line ${i}: This data is being corked.\n`);
    }
    
    // Uncork to flush the buffer - in real applications, you might cork/uncork
    // multiple times to batch writes together
    corkedStream.uncork();
    
    // End the stream
    corkedStream.end();
  });
  
  // Write without corking
  console.log('Writing without cork()...');
  for (let i = 0; i < 1000; i++) {
    uncorkedStream.write(`Line ${i}: This data is not being corked.\n`);
  }
  
  // End the stream
  uncorkedStream.end();
}

// Run the demonstration
demonstrateCorkUncork();
Misolni ishga tushirish »

Standart chiqishga yozish

Ushbu misol process.stdout WriteStream dan qanday foydalanishni ko‘rsatadi:

// process.stdout is a WriteStream

// Basic writing to stdout
process.stdout.write('Hello, ');
process.stdout.write('world!\n');

// Check if stdout supports color (most terminals do)
const supportsColor = process.stdout.hasColors && process.stdout.hasColors();

// Simple formatting if color is supported
if (supportsColor) {
  // ANSI escape codes for colors
  const colors = {
    red: '\x1b[31m',
    green: '\x1b[32m',
    yellow: '\x1b[33m',
    blue: '\x1b[34m',
    reset: '\x1b[0m'
  };
  
  process.stdout.write(`${colors.red}This text is red.\n${colors.reset}`);
  process.stdout.write(`${colors.green}This text is green.\n${colors.reset}`);
  process.stdout.write(`${colors.blue}This text is blue.\n${colors.reset}`);
} else {
  process.stdout.write('Your terminal does not support colors.\n');
}

// Writing tabular data
const table = [
  ['Name', 'Age', 'Country'],
  ['John', '28', 'USA'],
  ['Maria', '32', 'Spain'],
  ['Yuki', '24', 'Japan']
];

process.stdout.write('\nTable Example:\n');
table.forEach(row => {
  process.stdout.write(`${row[0].padEnd(10)}${row[1].padEnd(5)}${row[2]}\n`);
});

// Progress bar example
process.stdout.write('\nProgress Bar Example:\n');

function showProgress(percent) {
  const width = 40;
  const completed = Math.floor(width * (percent / 100));
  const remaining = width - completed;
  
  // Create the progress bar
  const bar = '[' + '#'.repeat(completed) + ' '.repeat(remaining) + ']';
  
  // Use \r to return to the beginning of the line
  process.stdout.write(`\r${bar} ${percent}%`);
  
  // When complete, add a newline
  if (percent === 100) {
    process.stdout.write('\nComplete!\n');
  }
}

// Simulate progress
let progress = 0;
const progressInterval = setInterval(() => {
  progress += 10;
  showProgress(progress);
  
  if (progress >= 100) {
    clearInterval(progressInterval);
  }
}, 300);

// Note: The progress bar example is more effective in a terminal
// than in the W3Schools TryIt editor
Misolni ishga tushirish »

HTTP WriteStream misoli

Ushbu misol HTTP javob ma’lumotlarini qayta ishlash uchun WriteStream dan qanday foydalanishni ko‘rsatadi:

const http = require('http');

// Create an HTTP server
const server = http.createServer((req, res) => {
  // res is an http.ServerResponse, which is a WriteStream
  console.log(`Received ${req.method} request to ${req.url}`);
  
  // Set response headers
  res.setHeader('Content-Type', 'text/html');
  
  // Check if the client requested a streaming response
  if (req.url === '/stream') {
    // Demonstrate streaming a large response
    streamLargeResponse(res);
  } else {
    // Default handler - show links to examples
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(`
      <!DOCTYPE html>
      <html>
      <head><title>HTTP WriteStream Example</title></head>
      <body>
        <h1>HTTP WriteStream Examples</h1>
        <ul>
          <li><a href="/stream">Stream a large response</a></li>
        </ul>
      </body>
      </html>
    `);
  }
});

// Function to stream a large response piece by piece
function streamLargeResponse(res) {
  // Set appropriate headers
  res.writeHead(200, {
    'Content-Type': 'text/html',
    'Transfer-Encoding': 'chunked'  // Enable chunked transfer encoding
  });
  
  // Write the HTML header
  res.write(`
    <!DOCTYPE html>
    <html>
    <head>
      <title>Streaming Response Example</title>
      <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .chunk { padding: 10px; margin: 5px; background-color: #f0f0f0; }
      </style>
    </head>
    <body>
      <h1>Streaming Response Example</h1>
      <p>This response is being streamed in chunks with delays between them.</p>
      <div id="chunks">
  `);
  
  // Number of chunks to send
  const totalChunks = 10;
  let sentChunks = 0;
  
  // Function to send a chunk
  function sendChunk() {
    sentChunks++;
    
    const now = new Date().toISOString();
    const chunk = `
      <div class="chunk">
        <h3>Chunk ${sentChunks} of ${totalChunks}</h3>
        <p>Sent at: ${now}</p>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam vehicula magna eros,
        eget gravida dolor fermentum non.</p>
      </div>
    `;
    
    // Write the chunk to the response
    res.write(chunk);
    
    // If we've sent all chunks, end the response
    if (sentChunks >= totalChunks) {
      // Write HTML footer
      res.end(`
        </div>
        <p>All chunks have been sent.</p>
      </body>
      </html>
      `);
      console.log('Finished streaming response');
    } else {
      // Otherwise, schedule the next chunk
      setTimeout(sendChunk, 500); // Send a chunk every 500ms
    }
  }
  
  // Start sending chunks
  console.log('Starting to stream response');
  sendChunk();
}

// Start the server
const PORT = 8080;
server.listen(PORT, () => {
  console.log(`HTTP WriteStream example server running at http://localhost:${PORT}`);
});

// Note: To see this in action, you need to run the server and open the browser at
// http://localhost:8080
Misolni ishga tushirish »

WriteStream’larda xatolarni qayta ishlash

Ushbu misol WriteStream’lar bilan ishlashda xatolarni to‘g‘ri qayta ishlashni ko‘rsatadi:

const fs = require('fs');
const path = require('path');

// Function to write to a file with proper error handling
function writeWithErrorHandling(filePath, data) {
  console.log(`Attempting to write to: ${filePath}`);
  
  // Create the WriteStream
  const writeStream = fs.createWriteStream(filePath);
  
  // Set up promise to capture result or error
  return new Promise((resolve, reject) => {
    // Handle errors
    writeStream.on('error', (err) => {
      console.error(`Error writing to ${filePath}: ${err.message}`);
      
      // Make sure the stream is destroyed properly
      writeStream.destroy();
      reject(err);
    });
    
    // Handle successful completion
    writeStream.on('finish', () => {
      console.log(`Successfully wrote ${writeStream.bytesWritten} bytes to ${filePath}`);
      resolve(writeStream.bytesWritten);
    });
    
    // Write the data
    writeStream.write(data, (err) => {
      if (err) {
        console.error(`Error during write operation: ${err.message}`);
        // The 'error' event will also be emitted in this case
      } else {
        console.log('Data written successfully, ending stream');
        writeStream.end();
      }
    });
  });
}

// Test with valid and invalid file paths
const validPath = path.join(__dirname, 'valid-path.txt');
const invalidPath = path.join('/', 'invalid', 'path', 'file.txt'); // Likely to be invalid on most systems

// Example 1: Writing to a valid path
console.log('Example 1: Writing to a valid path');
writeWithErrorHandling(validPath, 'This is test content for error handling example')
  .then(bytesWritten => {
    console.log(`Verified: ${bytesWritten} bytes written`);
    
    // Clean up the test file
    fs.unlinkSync(validPath);
    console.log('Test file removed');
    
    // Example 2: Writing to an invalid path
    console.log('\nExample 2: Writing to an invalid path');
    return writeWithErrorHandling(invalidPath, 'This should fail');
  })
  .catch(err => {
    console.log('Error caught in Promise catch:', err.message);
  });

// Example 3: Demonstrating destroyed streams
console.log('\nExample 3: Demonstrating destroyed streams');

function demonstrateDestroyedStream() {
  const destroyTestFile = path.join(__dirname, 'destroy-test.txt');
  const writeStream = fs.createWriteStream(destroyTestFile);
  
  writeStream.on('error', (err) => {
    console.error(`Destruction error: ${err.message}`);
  });
  
  writeStream.on('close', () => {
    console.log('Destroyed stream closed');
    
    // Clean up if the file was created
    if (fs.existsSync(destroyTestFile)) {
      fs.unlinkSync(destroyTestFile);
      console.log('Destroy test file removed');
    }
  });
  
  // Write some data
  writeStream.write('Initial data before destruction\n');
  
  // Destroy the stream with an error
  console.log('Deliberately destroying the stream');
  writeStream.destroy(new Error('Stream manually destroyed'));
  
  // Attempt to write after destruction (should fail silently)
  const writeResult = writeStream.write('This should not be written');
  console.log(`Attempt to write after destruction returned: ${writeResult}`);
}

demonstrateDestroyedStream();
Misolni ishga tushirish »

WriteStream’lar uchun eng yaxshi amaliyotlar

Node.js da WriteStream’lar bilan ishlashda quyidagi eng yaxshi amaliyotlarni ko‘rib chiqing:

      
  1. Xatolarni har doim qayta ishlang: Ushlanmagan istisnolarning (unhandled exceptions) oldini olish uchun WriteStream’lardagi 'error' hodisalarini har doim tinglang va qayta ishlang.
  2.   
  3. Backpressure’ni boshqaring: write() qaytaradigan qiymatga e’tibor bering va oqimni boshqarish hamda xotira muammolarining oldini olish uchun 'drain' hodisasidan foydalaning.
  4. Yozuvlarni guruhlash uchun cork() dan foydalaning: cork() va uncork() dan to‘plamli yozish operatsiyalari uchun foydalaning, ko‘plab kichik yozishlar uchun unumdorlikni oshiring.
  5. Resurslarni tozalash: Streamlar end() bilan to‘g‘ri yopilgan yoki kerak bo‘lmaganda destroy() bilan yo‘q qilinganligiga ishonch hosil qiling.
  6. Tegishli buffer o‘lchamlarini o‘rnating: Xotiradan foydalanishni nazorat qilish uchun highWaterMark opsiyasidan foydalaning, ayniqsa yuqori o‘tkazuvchanlikka ega ilovalar bilan ishlashda.
  7. Iloji bo‘lsa pipe() dan foydalaning: pipe() metodi backpressure’ni avtomatik ravishda boshqaradi va odatda oqimlarni ulashning eng yaxshi usuli hisoblanadi.
  8. Kodlashni ko‘rib chiqing: Matn bilan ishlashda setDefaultEncoding() bilan mos kodlashni o‘rnating.
  9. stream.finished() dan foydalaning: Tozalash uchun stream endi yozilmaydigan yoki xato yoki muddatidan oldin yopilganini aniqlash uchun stream modulidagi stream.finished() dan foydalaning.

W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!