30

我正在编写一个用 TypeScript 编写的字数统计程序,我试图在 Deno 中运行。我在没有参数的情况下调用它,只是deno ./word_count.ts,所以它应该具有默认的只读文件系统访问权限。我希望我可以使用带有URL 方案标准浏览器fetch()API从文件系统中读取,如下所示:file:

  word_count.ts
const countWords = (s: string): number =>
s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const main = async () => {
    const text = await (await fetch("file:///./input.txt")).text();
    const count = countWords(text);
    console.log(`I read ${count} words.`);
};

main();
  input.txt
The quick brown fox jumps over the lazy dog.

但是当我尝试时,我看到它fetch不支持fileURL:

Error: an error occurred trying to connect: invalid URL, scheme must be http
    at FetchResponse.onMsg (deno/js/fetch.ts:121:21)
    at FetchRequest.onMsg (deno/js/fetch.ts:152:19)
    at onFetchRes (deno/js/fetch.ts:28:8)
    at onMessage$1 (deno/js/main.ts:30:7)

如何在 Deno 中读取本地文件的内容?

4

3 回答 3

31

更新:async function main() { ... }不再需要包装代码,因为 Deno 现在支持顶层await

使用内置Deno.readTextFile

const countWords = (s: string): number =>
  s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const text = await Deno.readTextFile('input.txt');
const count = countWords(text);
console.log(`I read ${count} words.`);

请参阅以下文档:https ://doc.deno.land/builtin/stable#Deno.readTextFile

使用内置Deno.readFile

const countWords = (s: string): number =>
  s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const decoder = new TextDecoder('utf-8');

const text = decoder.decode(await Deno.readFile('input.txt'));
const count = countWords(text);
console.log(`I read ${count} words.`);

请注意,您需要将数据显式解码为 UTF-8。

请参阅以下文档:https ://deno.land/typedoc/index.html#readfile

使用阻塞读取

接受的答案使用readFileSync()which 是一个阻塞函数,因此不需要main()存在(更新:非阻塞也不再需要它)。一个简化(和工作)的例子是:asyncawait

const countWords = (s: string): number =>
  s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const decoder = new TextDecoder('utf-8');

const text = decoder.decode(Deno.readFileSync('input.txt'));
const count = countWords(text);
console.log(`I read ${count} words.`);

请注意,没有await任何地方,所以代码稍微简单一些(更新:在 Deno 支持顶级之前await,简单性的差异更大)但是Deno.readFileSync()会阻塞线程直到文件被读取 - 对于一个简单的脚本,它执行一系列像这个例子中的步骤这很好,但如果它在服务器的请求处理程序中,那么这将对性能造成灾难。

使用较低级别Deno.openDeno.readAll

const countWords = (s: string): number =>
  s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const decoder = new TextDecoder('utf-8');

const file = await Deno.open('input.txt');
const text = decoder.decode(await Deno.readAll(file));
const count = countWords(text);
console.log(`I read ${count} words.`);

您可以将前两行main()放在一行中:

const text = decoder.decode(await Deno.readAll(await Deno.open('input.txt')));

但它的可读性会降低。

请参阅以下文档:https ://deno.land/typedoc/index.html#readall

甚至更低级别Deno.openDeno.read

您甚至可以使用更低的杠杆Deno.read,但您还必须分配缓冲区

请参阅以下文档:https ://deno.land/typedoc/index.html#read

使用new File()抽象

还有一种用于读写文件的类式抽象。

请参阅以下文档:https ://deno.land/typedoc/classes/deno.file.html

于 2019-04-16T10:46:17.037 回答
6

已过时:这个答案已被移除'deno'模块以支持版本 v0.3.4Deno中的全局而被打破。

DenoreadFileSync(filename: string): Uint8Array在其标准库中包含一个函数,该函数可在特殊的导入路径中找到'deno'

import {readFileSync} from 'deno';

const bytes = readFileSync('./input.txt'); 

这会将文件的内容作为字节数组读取。如果文件包含您想要作为字符串的文本,如您的示例中所示,您可以使用标准的 ECMAScriptTextDecoder类(MDN 文档)。

const utf8Decoder = new TextDecoder('utf-8');
const string = utf8Decoder.decode(bytes);

对于原始示例,这给了我们:

  word_count.ts
import {readFileSync} from 'deno';

const countWords = (s: string): number =>
s.split(/\s+/g).filter(w => /[a-z0-9]/.test(w)).length;

const main = async () => {
    const decoder = new TextDecoder("utf-8");
    const bytes = readFileSync("./input.txt");
    const text = decoder.decode(bytes);
    const count = countWords(text);
    console.log(`I read ${count} words.`);
};

main();

这会产生所需的输出:

$ deno ./word_count.ts
我读了9个字。
于 2018-08-21T03:12:27.757 回答
3

标准0.62.0/德诺1.2.1+

由于std v0.62.0,readFileStr已从标准库readFileStrSync中删除。

Deno.readTextFileDeno.readTextFileSync拥有相同的 API,现在是要走的路。

(与writeFileStr/相同writeFileStrSync

于 2020-08-02T10:23:36.930 回答