Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I read a local file in Deno?

I'm writing a word count program written in TypeScript that I'm trying to run in Deno. I'm invoking it with no arguments, just deno ./word_count.ts, so it should have the default read-only filesystem access. I was hoping that I might be able to use the standard browser fetch() API with the file: URL scheme to read from the filesystem, like this:

  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. 

But when I try I see I see that fetch doesn't support file URLs:

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) 

How can I read the contents of a local file in Deno?

like image 894
Jeremy Avatar asked Aug 21 '18 03:08

Jeremy


People also ask

How do I read a local file in TypeScript?

Use the readFileSync() method to read a file's contents in TypeScript, e.g. readFileSync(join(__dirname, 'example. txt'), 'utf-8') . The method takes the path and encoding as parameters and returns the contents of the specified file.

How do you read a file in JavaScript?

To read a file, use FileReader , which enables you to read the content of a File object into memory. You can instruct FileReader to read a file as an array buffer, a data URL, or text.

Can browser read local file?

Web browsers (and JavaScript) can only access local files with user permission. To standardize the file access from the browser, the W3C published the HTML5 File API in 2014. It defines how to access and upload local files with file objects in web applications.

Is Deno open source?

Deno is a simple, modern, and secure runtime for JavaScript and TypeScript. It is an open source project created by Ryan Dahl, who developed Node. js.


1 Answers

(Update: wrapping code in async function main() { ... } is no longer needed because Deno now supports top-level await)

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

See the docs at: https://doc.deno.land/builtin/stable#Deno.readTextFile

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

Note that you need to explicitly decode the data as UTF-8.

See the docs at: https://deno.land/typedoc/index.html#readfile

Using blocking reads

The accepted answer uses readFileSync() which is a blocking function so the main() being async is not needed (Update: it is no longer needed for non-blocking await as well). A simplified (and working) example would be:

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

Note that there is no await anywhere, so the code is slightly simpler (Update: before Deno supported top-level await the difference in simplicity was bigger) but the Deno.readFileSync() will block the thread until the file is read - for a simple script that does a sequence of steps like in this example this is fine, but if it was inside a request handler in a server then it would be a disaster for the performance.

Using lower-level Deno.open and 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 file = await Deno.open('input.txt'); const text = decoder.decode(await Deno.readAll(file)); const count = countWords(text); console.log(`I read ${count} words.`); 

You could put the first two lines of main() in a single line:

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

but it would be less readable.

See the docs at: https://deno.land/typedoc/index.html#readall

Even lower-level Deno.open and Deno.read

You could use even lower-lever Deno.read but then you'd also have to allocate the buffers

See the docs at: https://deno.land/typedoc/index.html#read

Using new File() abstraction

There is also a class-style abstraction for reading and writing files.

See the docs at: https://deno.land/typedoc/classes/deno.file.html

like image 137
rsp Avatar answered Sep 18 '22 21:09

rsp