Loading page…
Rust walkthroughs
Loading page…
Tempfile is a crate for creating and managing temporary files and directories in Rust. It provides secure, automatic cleanup of temporary resources, handling edge cases like race conditions and ensuring files are properly deleted when no longer needed.
Key concepts:
When to use Tempfile:
When NOT to use Tempfile:
use tempfile::NamedTempFile;
use std::io::{Write, Read};
fn main() -> std::io::Result<()> {
// Create a named temporary file
let mut temp_file = NamedTempFile::new()?;
// Get the path
println!("Temp file: {:?}", temp_file.path());
// Write to it
writeln!(temp_file, "Hello, temp file!")?;
// Read it back
temp_file.seek(std::io::SeekFrom::Start(0))?;
let mut contents = String::new();
temp_file.read_to_string(&mut contents)?;
println!("Contents: {}", contents);
// File is automatically deleted when temp_file goes out of scope
Ok(())
}use tempfile::TempDir;
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
// Create a temporary directory
let temp_dir = TempDir::new()?;
println!("Temp dir: {:?}", temp_dir.path());
// Create files inside
let file_path = temp_dir.path().join("data.txt");
let mut file = File::create(&file_path)?;
writeln!(file, "Data in temp dir")?;
// Directory and contents deleted on drop
Ok(())
}use tempfile::tempfile;
use std::io::{Write, Read, Seek, SeekFrom};
fn main() -> std::io::Result<()> {
// Create an anonymous temp file (no path, more secure)
let mut file = tempfile()?;
// Write data
file.write_all(b"Anonymous temp data")?;
// Read back
file.seek(SeekFrom::Start(0))?;
let mut buf = Vec::new();
file.read_to_end(&mut buf)?;
println!("Read: {}", String::from_utf8_lossy(&buf));
// File deleted on close (or drop)
Ok(())
}use tempfile::SpooledTempFile;
use std::io::{Write, Read, Seek, SeekFrom};
fn main() -> std::io::Result<()> {
// In-memory buffer up to 1KB, then spills to disk
let mut spool = SpooledTempFile::new(1024);
// Small data stays in memory
write!(spool, "Small data")?;
// Check if still in memory
if spool.is_rolled_over() {
println!("Data spilled to disk");
} else {
println!("Data still in memory");
}
// Large data spills to disk
let large_data = vec![0u8; 2048];
spool.write_all(&large_data)?;
if spool.is_rolled_over() {
println!("Now spilled to disk");
}
Ok(())
}use tempfile::NamedTempFile;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
writeln!(temp, "Important data")?;
// Persist the file at a specific location
let persisted = temp.persist("/tmp/important.txt")?;
println!("File persisted to: {:?}", persisted.path());
// File is no longer temporary - won't be deleted on drop
Ok(())
}use tempfile::NamedTempFile;
use std::io::Write;
fn main() -> std::io::Result<()> {
// Create temp file in specific directory
let mut temp = NamedTempFile::new_in("./output")?;
writeln!(temp, "In custom location")?;
println!("Created in: {:?}", temp.path().parent().unwrap());
Ok(())
}use tempfile::Builder;
fn main() -> std::io::Result<()> {
// Named temp file with prefix/suffix
let temp = Builder::new()
.prefix("myapp_")
.suffix(".tmp")
.tempfile()?;
println!("Temp file: {:?}", temp.path());
// Temp dir with prefix
let dir = Builder::new()
.prefix("myapp_session_")
.tempdir()?;
println!("Temp dir: {:?}", dir.path());
Ok(())
}use tempfile::NamedTempFile;
use std::io::{Write, Read};
fn process_file(path: &std::path::Path) -> std::io::Result<String> {
let mut file = std::fs::File::open(path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents.to_uppercase())
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::NamedTempFile;
use std::io::Write;
#[test]
fn test_process_file() {
let mut temp = NamedTempFile::new().unwrap();
write!(temp, "hello world").unwrap();
let result = process_file(temp.path()).unwrap();
assert_eq!(result, "HELLO WORLD");
}
}
fn main() {
println!("Run tests with: cargo test");
}use tempfile::NamedTempFile;
use std::io::{Write, Seek, SeekFrom};
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
// Write initial data
writeln!(temp, "Line 1")?;
// Seek to end for append
temp.seek(SeekFrom::End(0))?;
writeln!(temp, "Line 2")?;
// Read all
temp.seek(SeekFrom::Start(0))?;
let mut contents = String::new();
std::io::Read::read_to_string(&mut temp, &mut contents)?;
println!("{}", contents);
Ok(())
}use tempfile::NamedTempFile;
use std::io::{Write, Read};
fn producer(temp: &mut NamedTempFile) -> std::io::Result<()> {
writeln!(temp, "Produced data")?;
temp.flush()?;
Ok(())
}
fn consumer(temp: &mut NamedTempFile) -> std::io::Result<String> {
use std::io::Seek;
temp.seek(std::io::SeekFrom::Start(0))?;
let mut data = String::new();
temp.read_to_string(&mut data)?;
Ok(data)
}
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
producer(&mut temp)?;
let result = consumer(&mut temp)?;
println!("Consumed: {}", result);
Ok(())
}use tempfile::NamedTempFile;
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
writeln!(temp, "Data")?;
// Convert to regular File (loses automatic cleanup!)
let file: File = temp.into_file();
// Now you manage the file manually
// Or keep the NamedTempFile for auto-cleanup
// let file: &File = temp.as_file();
Ok(())
}use tempfile::TempDir;
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
let dir = TempDir::new()?;
// Create multiple files
for i in 0..5 {
let path = dir.path().join(format!("file{}.txt", i));
let mut file = File::create(path)?;
writeln!(file, "Content {}", i)?;
}
// List files
for entry in std::fs::read_dir(dir.path())? {
let entry = entry?;
println!("File: {:?}", entry.file_name());
}
// All deleted with dir on drop
Ok(())
}use tempfile::NamedTempFile;
use std::io::Write;
fn write_config() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
// Write data
write!(temp, "config data")?;
// Simulate error - temp file is cleaned up
// return Err(std::io::Error::new(std::io::ErrorKind::Other, "oops"));
// Or persist on success
temp.persist("config.txt")?;
Ok(())
}
fn main() {
match write_config() {
Ok(()) => println!("Config saved"),
Err(e) => eprintln!("Error: {}", e),
}
}use tempfile::NamedTempFile;
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
// Write large data in chunks
for chunk in 0..100 {
let data = vec![chunk as u8; 1024]; // 1KB chunks
temp.write_all(&data)?;
}
println!("Wrote {} bytes", temp.as_file().metadata()?.len());
Ok(())
}use tempfile::NamedTempFile;
use std::io::{Write, Copy};
// Simulated download function
fn download_to_temp(url: &str) -> std::io::Result<NamedTempFile> {
let mut temp = NamedTempFile::new()?;
// Simulate downloading
writeln!(temp, "Downloaded from: {}", url)?;
Ok(temp)
}
fn main() -> std::io::Result<()> {
let temp = download_to_temp("https://example.com/file")?;
// Process downloaded data
println!("Downloaded to: {:?}", temp.path());
// Or persist to final location
temp.persist("downloaded_file.txt")?;
Ok(())
}use tempfile::NamedTempFile;
use std::io::Write;
use std::path::Path;
fn atomic_write(path: &Path, content: &str) -> std::io::Result<()> {
// Create temp file in same directory for atomic rename
let mut temp = NamedTempFile::new_in(path.parent().unwrap())?;
// Write content
write!(temp, "{}", content)?;
temp.flush()?;
// Atomic rename (persist)
temp.persist(path)?;
Ok(())
}
fn main() -> std::io::Result<()> {
atomic_write(std::path::Path::new("config.txt"), "config data")?;
println!("Wrote atomically");
Ok(())
}use tempfile::NamedTempFile;
use std::fs::File;
fn main() -> std::io::Result<()> {
let mut temp = NamedTempFile::new()?;
// Get reference to underlying File
let file: &File = temp.as_file();
println!("Metadata: {:?}", file.metadata()?);
// Get mutable reference
let file_mut: &mut File = temp.as_file_mut();
println!("Can modify: {:?}", file_mut);
Ok(())
}use tempfile::NamedTempFile;
fn main() {
match NamedTempFile::new() {
Ok(temp) => {
println!("Created: {:?}", temp.path());
}
Err(e) => {
eprintln!("Failed to create temp file: {}", e);
// Common errors:
// - No permission
// - Disk full
// - Invalid path
}
}
}use tempfile::TempDir;
use std::path::PathBuf;
fn main() -> std::io::Result<()> {
let temp_dir = TempDir::new()?;
// Get path without keeping TempDir alive
// WARNING: No automatic cleanup!
let path: PathBuf = temp_dir.into_path();
println!("Path: {:?}", path);
// Now you must clean up manually
// std::fs::remove_dir_all(&path)?;
Ok(())
}use tempfile::{tempfile, NamedTempFile, SpooledTempFile};
fn main() -> std::io::Result<()> {
// tempfile() - Anonymous, no path, most secure
let anon = tempfile()?;
// No .path() method - can't access by path
// NamedTempFile - Has path, can be reopened
let named = NamedTempFile::new()?;
println!("Named path: {:?}", named.path());
// SpooledTempFile - In memory up to limit
let spooled = SpooledTempFile::new(1024);
// No .path() - may or may not be on disk
println!("Three types created");
Ok(())
}Tempfile Key Imports:
use tempfile::{NamedTempFile, TempDir, tempfile, tempdir, SpooledTempFile, Builder};Main Types:
| Type | Description | Auto-Cleanup |
|------|-------------|--------------|
| NamedTempFile | Temp file with path | Yes |
| TempDir | Temporary directory | Yes |
| tempfile() | Anonymous temp file | Yes |
| SpooledTempFile | In-memory with disk spill | Yes |
Builder Pattern:
let temp = Builder::new()
.prefix("app_")
.suffix(".tmp")
.tempfile()?;Key Methods:
// NamedTempFile
temp.path(); // Get path
temp.as_file(); // Get &File
temp.persist(path); // Keep file permanently
// TempDir
dir.path(); // Get path
dir.into_path(); // Keep dir (no cleanup)Key Points:
persist() to keep filesnew_in() for custom locationtempfile() is most secure (anonymous)SpooledTempFile for memory efficiencyCommon Patterns:
let temp = NamedTempFile::new()?;
// use temp.path() in testslet temp = NamedTempFile::new_in(dir)?;
temp.persist(final_path)?;let mut spool = SpooledTempFile::new(max_memory);