Как мне прочитать локальный файл в Deno?
Я пишу программу подсчета слов, написанную на TypeScript, которую я пытаюсь запустить в Deno. Я вызываю это без аргументов, просто deno ./word_count.ts
поэтому он должен иметь доступ по умолчанию к файловой системе только для чтения. Я надеялся, что смогу использовать стандартный браузер fetch()
API с file:
Схема URL для чтения из файловой системы, например:
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?
1 ответ
Дено включает в себя readFileSync(filename: string): Uint8Array
функция в стандартной библиотеке, которая доступна по специальному пути импорта 'deno'
,
import {readFileSync} from 'deno';
const bytes = readFileSync('./input.txt');
Это читает содержимое файла как байтовый массив. Если файл содержит текст, который вы хотите в виде строки, как в вашем примере, вы можете использовать стандартный ECMAScript TextDecoder
класс ( 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 слов.
С помощью 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/t ypedoc/index.html.
Использование блокировки чтения
Принятый ответ использует 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.`);
Обратите внимание, что нет async
нет main()
и нет await
где угодно, код проще, но Deno.readFileSync()
будет блокировать поток до тех пор, пока файл не будет прочитан - для простого скрипта, который выполняет последовательность шагов, как в этом примере, это нормально, но если бы он был внутри обработчика запросов на сервере, это было бы катастрофой для производительности.
Использование нижнего уровня Deno.open
а также Deno.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/t ypedoc/index.html.
Еще более низкий уровень Deno.open
а также Deno.read
Вы могли бы использовать даже нижний рычаг Deno.read
но тогда вы также должны были бы выделить буферы
См. Документы по адресу: https://deno.land/t ypedoc/index.html
С помощью new File()
абстракция
Существует также абстракция в стиле класса для чтения и записи файлов.
См. Документы по адресу: https://deno.land/t ypedoc/classes/deno.file.html
стандартное 0.62.0
/ Deno 1.2.1
+
поскольку std v0.62.0
, readFileStr
а также readFileStrSync
будут удалены из стандартной библиотеки.
Deno.readTextFile
а также Deno.readTextFileSync
имеют тот же API, и теперь это лучший способ.
(то же самое для writeFileStr
/ writeFileStrSync
)