I/O Operations
File and console I/O in Oxide uses Rust's standard library directly. This page documents common I/O patterns using Oxide syntax.
File I/O
File operations use Rust's std::fs module:
Reading Files
import std.fs
fn main() {
// Read entire file to string
let content = fs.readToString("config.txt")
match content {
Ok(text) -> println!("Content: $text")
Err(e) -> println!("Error: $e")
}
// With try? - returns optional
let content = try? fs.readToString("config.txt")
if let text = content {
println!("Content: $text")
}
// With do-catch
do {
let content = try fs.readToString("data.txt")
process(content)
} catch {
println!("Error reading file: $error")
}
}
Writing Files
import std.fs
fn main() {
// Write string to file
do {
try fs.write("output.txt", "Hello, World!")
println!("File written successfully")
} catch {
println!("Error writing: $error")
}
}
Checking File Existence
import std.path.Path
fn main() {
let path = Path.new("config.toml")
if path.exists() {
let config = try? fs.readToString("config.toml")
// process config
} else {
println!("Config not found, using defaults")
}
}
Reading Lines
import std.fs
import std.io.BufRead
import std.io.BufReader
fn main() {
do {
let file = try fs.File.open("data.txt")
let reader = BufReader.new(file)
for line in reader.lines() {
match line {
Ok(text) -> println!("Line: $text")
Err(e) -> println!("Error: $e")
}
}
} catch {
println!("Error: $error")
}
}
Console I/O
Printing
fn main() {
// Print with newline
println!("Hello, World!")
// Print without newline
print!("Enter name: ")
// Debug print
let numbers = [1, 2, 3]
println!("Numbers: #numbers") // Uses {:?} format
}
Reading User Input
import std.io
import std.io.BufRead
fn main() {
print!("Enter your name: ")
io.stdout().flush() // Ensure prompt is displayed
var input = String.new()
io.stdin().readLine(&mut input)
let name = input.trim()
println!("Hello, $name!")
}
Practical Examples
Config File Reading
import std.fs
import std.path.Path
struct Config(
host: String,
port: Int,
debug: Bool
)
fn loadConfig(path: String): Config {
let defaults = Config(
host = "localhost",
port = 8080,
debug = false
)
guard Path.new(path).exists() else {
return defaults
}
let content = try? fs.readToString(path) ?? ""
// Parse simple key=value format
var config = defaults
for line in content.lines() {
let parts: Array<&str> = line.split("=").collect()
if parts.len() == 2 {
let key = parts[0].trim()
let value = parts[1].trim()
match key {
"host" -> config.host = value.toString()
"port" -> config.port = value.parse<Int>().unwrapOr(8080)
"debug" -> config.debug = value == "true"
else -> ()
}
}
}
config
}
Logging to File
import std.fs.OpenOptions
import std.io.Write
fn log(message: String) {
let entry = "[LOG] $message\n"
do {
var file = try OpenOptions.new()
.append(true)
.create(true)
.open("app.log")
try file.writeAll(entry.asBytes())
} catch {
eprintln!("Failed to write log: $error")
}
}
fn main() {
log("Application started")
// ... application code ...
log("Application finished")
}
Interactive Input Loop
import std.io
import std.io.BufRead
fn readValidNumber(): Int {
loop {
print!("Enter a positive number: ")
io.stdout().flush()
var input = String.new()
io.stdin().readLine(&mut input)
if let num = input.trim().parse<Int>().ok() {
if num > 0 {
return num
}
}
println!("Invalid input, try again")
}
}
Error Handling Patterns
Using try?
Best for optional results where errors can be handled with defaults:
let content = try? fs.readToString("optional.txt")
let text = content ?? "default content"
Using try!
For situations where failure indicates a bug or unrecoverable state:
// In tests
let testData = try! fs.readToString("test_fixtures/data.json")
// Required files
let required = try! fs.readToString("critical.conf")
Using do-catch
For comprehensive error handling:
fn processFiles(paths: Array<String>) {
for path in paths {
do {
let content = try fs.readToString(path)
let result = try process(content)
try fs.write("output_$path", result)
} catch {
println!("Error processing $path: $error")
// Continue with next file
}
}
}
Comparison with Rust
| Oxide | Rust |
|---|---|
fs.readToString(p) | std::fs::read_to_string(p) |
fs.write(p, c) | std::fs::write(p, c) |
Path.new(p).exists() | std::path::Path::new(p).exists() |
io.stdin().readLine(&mut s) | std::io::stdin().read_line(&mut s) |
file.writeAll(b) | file.write_all(b) |
See Also
- Error Handling - throws, try, do-catch
- Standard Library Overview