I was trying to write to a file using Deno.writeFile
await Deno.writeFile('./file.txt', 'some content')
But got the following cryptic error:
error: Uncaught TypeError: arr.subarray is not a function
at Object.writeAll ($deno$/buffer.ts:212:35)
at Object.writeFile ($deno$/write_file.ts:70:9)
What's the right way to write files in Deno?
There are multiple ways to write a file in Deno, all of them require --allow-write flag and will throw if an error occurred, so you should handle errors correctly.
Deno.writeFile
This API takes a Uint8Array, not a string, the reason why you get that error. It also takes an optional WriteFileOptions object
const res = await fetch('http://example.com/image.png');
const imageBytes = new Uint8Array(await res.arrayBuffer());
await Deno.writeFile('./image.png', imageBytes);
There's also the synchronous API (it blocks the event loop as it does in Node.js).
Deno.writeFileSync('./image.png', imageBytes);
The easiest way is to use Deno.writeTextFile
await Deno.writeTextFile('./file.txt', 'some content');
You can also use Deno.writeFile with TextEncoder.
const encoder = new TextEncoder(); // to convert a string to Uint8Array
await Deno.writeFile('./file.txt', encoder.encode('some content'));
Deno.open returns a FsFile which contains a WritableStream in .writable property, so you can just pipe a stream directly to it.
const res = await fetch('https://example.com/csv');
const file = await Deno.open('./some.csv', { create: true, write: true })
await res.body.pipeTo(file.writable);
file.close();
If you have a Reader instead of a ReadableStream you can convert it to a ReadableStream using readableStreamFromReader from std/streams:
import { readableStreamFromReader } from "https://deno.land/[email protected]/streams/mod.ts?s=readableStreamFromReader";
// ...
const readable = readableStreamFromReader(someReader);
await readable.pipeTo(file.writeable)
Using Deno.open and Deno.writeAll (or Deno.writeAllSync)
const file = await Deno.open('./image.png', { write: true, create: true });
/* ... */
await Deno.writeAll(file, imageBytes);
file.close(); // You need to close it!
See OpenOptions here. If you want to append you would do:
{ append: true }
And you can also use even lower-level APIs such as Deno.write or Writer.write
You can use ensureDir to safely write files to possibly non-existent directories:
import { ensureDir } from "https://deno.land/[email protected]/fs/ensure_dir.ts";
ensureDir("./my/dir")
.then(() => Deno.writeTextFile("./my/dir/file.txt", "some content"));
The containing file directory can be derived via dirname:
import { dirname } from "https://deno.land/[email protected]/path/mod.ts";
const file = "./my/dir/file.txt";
ensureDir(dirname(file)).then(() => Deno.writeTextFile(file, "some content"));
An alternative is ensureFile to assert file existence:
import { ensureFile } from "https:deno.land/std/fs/ensure_file.ts";
ensureFile(file).then(/* your file write method */)
This variant is slightly less verbose, with the cost of one additional write operation (file creation, if not exists).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With