Skip to content

Commit f7b68ab

Browse files
committed
feat: more progress on the article
1 parent 42cdbd0 commit f7b68ab

File tree

1 file changed

+21
-5
lines changed
  • src/content/blog/reading-writing-files-nodejs

1 file changed

+21
-5
lines changed

src/content/blog/reading-writing-files-nodejs/index.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,17 @@ async function createBeepWav() {
176176
await createBeepWav()
177177
```
178178

179-
When working with binary data like this, we use the Node.js [Buffer](https://nodejs.org/api/buffer.html) object to organize and manipulate the binary data. A Buffer is a fixed-size sequence of bytes that provides a way to work with binary data directly. It's similar to an array of integers, but specifically designed for handling raw binary data efficiently. In our WAV example, we use `Buffer.alloc()` to create a buffer of the required size, then use methods like `writeUInt32LE()` and `writeInt16LE()` to write specific data types at specific positions in little-endian format. If you are curious to find out more about the binary structure of a WAV file, you can check out this excellent page on [Wikipedia](https://en.wikipedia.org/wiki/WAV).
179+
This example demonstrates several key concepts for binary file manipulation in Node.js. The `encodeWavPcm16()` function creates a complete WAV file structure by constructing both the header and audio data sections. The WAV header contains metadata like file size, audio format, sample rate, and number of channels, while the data section contains the actual audio samples.
180+
181+
The `generateBeepTone()` function creates audio samples using a sine wave mathematical formula, generating a pure tone at the specified frequency. Each sample represents the amplitude of the sound wave at a specific point in time, and when played back at the correct sample rate, these digital values recreate the original analog sound.
182+
183+
Don't worry too much about the specifics of this example dealing with the WAV binary format - what matters here is learning that we can put arbitrary binary data into a buffer and write it into a file using `writeFile()`. The key takeaway is that Node.js treats all file operations the same way, whether you're writing text, JSON, images, audio, or any other type of data.
184+
185+
When working with binary data like this, we use the Node.js [Buffer](https://nodejs.org/api/buffer.html) object to organize and manipulate the binary data. A Buffer is a fixed-size sequence of bytes that provides a way to work with binary data directly. It's similar to an array of integers, but specifically designed for handling raw binary data efficiently. In our WAV example, we use `Buffer.alloc()` to create a buffer of the required size, then use methods like `writeUInt32LE()` and `writeInt16LE()` to write specific data types at specific positions in little-endian format.
186+
187+
:::note[WAV Binary File Structure]
188+
If you are curious to find out more about the binary structure of a WAV file, you can check out this excellent page on [Wikipedia](https://en.wikipedia.org/wiki/WAV).
189+
:::
180190

181191
#### Reading Binary Data - Parse WAV file header
182192

@@ -255,6 +265,12 @@ if (!filePath) {
255265
await getWavDuration(filePath)
256266
```
257267

268+
This example showcases the reverse process - reading and parsing binary data from an existing WAV file. The `decodeWavHeader()` function demonstrates how to extract specific information from binary data by reading bytes at predetermined positions within the file structure.
269+
270+
The function uses Buffer methods like `readUInt32LE()` and `readUInt16LE()` to interpret raw bytes as specific data types. For example, bytes 22-23 contain the number of channels, bytes 24-27 contain the sample rate, and bytes 40-43 contain the size of the audio data. By knowing the WAV file format specification, we can locate and extract these values.
271+
272+
The duration calculation combines several pieces of metadata: we divide the total audio data size by the byte rate (bytes per second) to get the duration in seconds, then multiply by 1000 to convert to milliseconds. This demonstrates how understanding both the file format and basic math allows us to derive meaningful information from binary data.
273+
258274
You can try out this example with the beep WAV files we created in the previous example or, if you need some longer free WAV files, you can check out a website with free audio samples like [Zapsplat](https://www.zapsplat.com/).
259275

260276
:::note[Binary file complexity]
@@ -306,7 +322,7 @@ This concurrent approach provides a significant performance improvement. If we u
306322

307323
#### Writing Multiple Files Concurrently
308324

309-
```javascript
325+
```javascript {26-29}
310326
// write-multiple-files.js
311327
import { writeFile } from 'node:fs/promises'
312328

@@ -335,8 +351,8 @@ async function generateReports(data) {
335351
const promises = reports.map(({ filename, content }) =>
336352
writeFile(filename, content, 'utf8'),
337353
)
338-
339354
await Promise.all(promises)
355+
340356
console.log(`Successfully generated ${reports.length} report files`)
341357
} catch (error) {
342358
console.error('Failed to write report files:', error.message)
@@ -486,7 +502,7 @@ Notice that when using `readFileSync()` and `writeFileSync()` we are not using `
486502
487503
However, if you care about extreme performance, there are specific cases where you might prefer the sync methods. Sync methods can occasionally be faster because they don't need to give back control to the event loop and, for example in the case of reading a file, the content of the file is immediately available once the filesystem operation completes without having to wait for the event loop to capture the event and give back control to our code. One case that comes to mind is when writing **non-concurrent CLI apps or scripts** that need to read or write a file before continuing with the next operation.
488504
489-
:::danger[Never Use Sync Methods in Concurrent Environments]
505+
:::warning[Never Use Sync Methods in Concurrent Environments]
490506
**Do not use sync methods in concurrent environments such as web servers.** While you read or write a file synchronously, you will be blocking the event loop, which means that no other user requests will be processed during that time.
491507
492508
This can cause noticeable delays for users - if a file operation takes 100ms, every user trying to access your server during that time will experience a 100ms delay. In a web application, this is unacceptable.
@@ -502,7 +518,7 @@ This can cause noticeable delays for users - if a file operation takes 100ms, ev
502518
- Web servers (Express, Fastify, etc.)
503519
- Real-time applications
504520
- Any concurrent environment
505-
:::
521+
:::
506522
507523
## Working with Large Files: Memory Considerations
508524

0 commit comments

Comments
 (0)