Compile-time code, 4 of 4
Embedding files
Build files into the executable with Embed, EmbedText, and EmbedFolder, so a program ships as one file.
What you’ll build
A greeting program whose help text and greetings are files beside its code, built into the executable, so it needs nothing beside it when it runs. You’ll embed one file as text, one as bytes, and a whole folder.
A file as text
EmbedText(path) reads a file when the program is built and gives its text as a String known
at compile time, which a Const can hold. The path is from the folder of the file the call is in.
Usage: greet [name]
Prints a greeting in each language it knows.Import std.core
Import std.text
Const HELP = EmbedText("help.txt")
Print(HELP.TrimEnd())Usage: greet [name] Prints a greeting in each language it knows.
The text is in the executable: move the program anywhere, delete help.txt, and it still prints
it. Change help.txt, and the next build has the new text. The file must be UTF-8.
A file as bytes
Embed(path) gives a file’s bytes, exactly as they are, in a new UInt8[] each time it runs.
It’s for files that aren’t text, like images or archives, or for text you’ll decode yourself.
Usage: greet [name]
Prints a greeting in each language it knows.Import std.core
Local bytes = Embed("help.txt")
Print("help.txt is {bytes.Count} bytes, starting with {bytes[0]}")help.txt is 65 bytes, starting with 85
A whole folder
EmbedFolder(path) gives a new Map<String, UInt8[]> of every file in a folder and its folders,
by its path in the folder, like "formal/en.txt", in path order. Hidden files and folders, whose
names start with ., are left out.
Hello, {name}!Hola, {name}!Good day, {name}.Import std.core
Import std.collections
Import std.text
Local greetings = EmbedFolder("greetings")
For path In greetings.Keys()
Local greeting = String.FromUtf8(greetings[path]) ?? ""
Print("{path}: {greeting.TrimEnd().Replace("{{name}}", "Ada")}")
End Foren.txt: Hello, Ada! es.txt: Hola, Ada! formal/en.txt: Good day, Ada.
String.FromUtf8 gives Null for bytes that aren’t valid UTF-8, so the code gives "" then.
In the string, {{ and }} stand for the braces themselves, since a lone { starts an
interpolation.
Mistakes found at build time
A path that names nothing is an error where it’s written, so a missing file never reaches a running program:
Import std.core
Const HELP = EmbedText("nope.txt")
Print(HELP) Compiling main.fb
main.fb:3:24: error: "nope.txt" isn't a file: there's nothing at nope.txt
|
3 | Const HELP = EmbedText("nope.txt")
| ^^^^^^^^^^
error: couldn't build main.fb because of 1 errorA path also has to stay inside the package’s folder, or for a program without a project.toml,
the main file’s folder:
Import std.core
Local notes = Embed("../notes.txt")
Print(notes.Count) Compiling main.fb
main.fb:3:21: error: "../notes.txt" leaves the main file's folder, which a program's embedded files are in
|
3 | Local notes = Embed("../notes.txt")
| ^^^^^^^^^^^^^^
error: couldn't build main.fb because of 1 errorOne call can embed at most 64 MiB. A file bigger than that is better read when the program runs, with std.io.
What you learned
EmbedTextbuilds a UTF-8 file into the program as a String known at compile time.Embedbuilds in a file’s bytes, andEmbedFoldera folder’s files, by their paths.- Paths are from the calling file’s folder, and stay inside the package.
- A missing file is a build error, and each build reads the files again.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.