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

时间:2018-08-21 03:12:28

标签: typescript deno

我正在编写一个用TypeScript编写的单词计数程序,试图在Deno中运行。我在调用时没有参数,只是deno ./word_count.ts,因此它应该具有默认的只读文件系统访问权限。我希望我可以将the standard browser fetch() APIthe file: URL scheme一起使用来从文件系统读取,就像这样:

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不支持file URL:

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中读取本地文件的内容?

3 个答案:

答案 0 :(得分:6)

  

已过时::删除了'deno'模块,转而使用了release v0.3.4中的Deno全局。

Deno在其标准库中包含一个readFileSync(filename: string): Uint8Array函数,可在特殊的导入路径'deno'中使用该函数。

import {readFileSync} from 'deno';

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

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

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
I read 9 words.

答案 1 :(得分:2)

使用readFileStr中的deno_std

使用readFileStr中的std/fs的示例:

import { readFileStr } from 'https://deno.land/std/fs/mod.ts';

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

const main = async () => {
  const text = await readFileStr('input.txt');
  const count = countWords(text);
  console.log(`I read ${count} words.`);
};

main();

只需将第一行更改为以下内容,即可使用readFileStr中的std/fs来减少下载量:

import { readFileStr } from 'https://deno.land/std/fs/read_file_str.ts';

查看文档,网址为:https://github.com/denoland/deno_std

使用内置的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 main = async () => {
  const text = decoder.decode(await Deno.readFile('input.txt'));
  const count = countWords(text);
  console.log(`I read ${count} words.`);
};

main();

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

查看文档,网址为:https://deno.land/typedoc/index.html#readfile

使用分块读取

接受的答案使用readFileSync()这是一个阻止函数,因此不需要main()async。一个简化的(有效的)示例是:

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.`);

请注意,在任何地方都没有asyncmain()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 main = async () => {
  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();

您可以将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

答案 2 :(得分:2)

std 0.62.0 / Deno 1.2.1 +

由于std v0.62.0readFileStrreadFileStrSync来自标准库,removed

Deno.readTextFileDeno.readTextFileSync具有相同的API,现在是可行的方法。

(与writeFileStr / writeFileStrSync相同)