1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const fs = require('fs')
const {Transform} = require('stream')
class ReplaceStream extends Transform {
// `oldString` is the text to replace; `newString` is the replacement
constructor(oldString, newString) {
super({decodeStrings: false}) // take in string chunks
this.setEncoding('utf8') // output string chunks
this.oldString = oldString
this.newString = newString
// We store the end of the previous chunk
// in case `oldString` straddles a chunk boundary
this.remainingChunk = ''
}
_transform(chunk, encoding, callback) {
// Find the strings between occurrences of `oldString`
const betweenStrings = (this.remainingChunk + chunk).split(this.oldString)
const lastString = betweenStrings.pop()
// Write out each `betweenString`,
// then replace the occurrence of `oldString` with `newString`
for (const betweenString of betweenStrings) {
this.push(betweenString, encoding)
this.push(this.newString, encoding)
}
// Keep the last few characters in case `oldString` is split across chunks
this.push(lastString.slice(0, -this.oldString.length))
this.remainingChunk = lastString.slice(-this.oldString.length)
callback()
}
// Called after all chunks have been transformed
_flush(callback) {
// Write the end of the last chunk
this.push(this.remainingChunk)
// As in `_transform()`, `callback` must be called when done
callback()
}
}
fs.createReadStream('source.txt', 'utf8')
.pipe(new ReplaceStream('here', 'there')) // replace 'here' with 'there'
.pipe(new ReplaceStream('yes', 'no')) // and 'yes' with 'no'
.pipe(fs.createWriteStream('destination.txt'))