Code Examples for Reading 16
Download
You can also download a ZIP file containing this code.
Words1.ts
import fs from 'fs';
import path from 'path';
/**
* Words example: familiar TS implementation
*/
/**
* Find names of all files in the filesystem subtree rooted at folder.
* @param folder root of subtree, requires fs.lstatSync(folder).isDirectory() === true
* @returns array of names of all ordinary files (not folders) that have folder as
* their ancestor
*/
function allFilesIn(folder: string): Array<string> {
let files: Array<string> = [];
for (const child of fs.readdirSync(folder)) {
const fullNameOfChild = path.join(folder, child);
if (fs.lstatSync(fullNameOfChild).isDirectory()) {
files = files.concat(allFilesIn(fullNameOfChild));
} else if (fs.lstatSync(fullNameOfChild).isFile()) {
files.push(fullNameOfChild);
}
}
return files;
}
/**
* Filter an array of files to those that end with suffix.
* @param filenames array of filenames
* @param suffix string to test
* @returns a new array consisting of only those files whose names end with suffix
*/
function onlyFilesWithSuffix(filenames: Array<string>, suffix: string): Array<string> {
const result: Array<string> = [];
for (const f of filenames) {
if (f.endsWith(suffix)) {
result.push(f);
}
}
return result;
}
/**
* Find all the non-word-character-separated words in files.
* @param filenames list of files (all non-null)
* @returns list of words from all the files
* @throws IOException if an error occurs reading a file
*/
function getWords(filenames: Array<string>): Array<string> {
const words: Array<string> = [];
for (const f of filenames) {
const data = fs.readFileSync(f, { encoding: "utf8", flag: "r" });
const lines = data.split(/\r?\n/);
for (const line of lines) {
// split on \W (non-word characters, like spaces and punctuation)
for (const word of line.split(/\W+/)) {
// split can return empty strings, so omit them
if (word.length > 0) {
words.push(word);
}
}
}
}
return words;
}
const allFiles = allFilesIn(".");
const tsFiles = onlyFilesWithSuffix(allFiles, ".ts");
const words = getWords(tsFiles);
for (const s of words) { console.log(s); }
Words2.ts
import fs from 'fs';
import path from 'path';
/**
* Words example: TS implementation with map/filter/reduce
*/
/**
* Find all files in the filesystem subtree rooted at folder.
* @param folder root of subtree, requires folder.isDirectory() == true
* @returns stream of all ordinary files (not folders) that have folder as
* their ancestor
*/
function allFilesIn(folder: string): Array<string> {
const children: Array<string> = fs.readdirSync(folder)
.map(f => path.join(folder, f));
const descendants: Array<string> = children
.filter(f => fs.lstatSync(f).isDirectory())
.map(allFilesIn)
.flat();
return [
...descendants,
...children.filter(f => fs.lstatSync(f).isFile())
];
}
/**
* Make a filename suffix testing predicate.
* @param suffix string to test
* @returns a predicate that returns true iff the filename ends with suffix.
*/
function endsWith(suffix: string): (filename: string) => boolean {
return (filename: string) => filename.endsWith(suffix);
}
const filenames: Array<string> = allFilesIn(".")
.filter(s => s.endsWith(".ts"));
const fileContents: Array<Array<string>> = filenames.map(f => {
const data = fs.readFileSync(f, { encoding: "utf8", flag: "r" });
return data.split(/\r?\n/);
});
const lines: Array<string> = fileContents.flat();
const words: Array<string> = lines.map(line => line.split(/\W+/)
.filter(s => s.length > 0))
.flat();
words.forEach(s => console.log(s));