tokio/fs/read.rs
1use crate::fs::asyncify;
2
3use std::{io, path::Path};
4
5/// Reads the entire contents of a file into a bytes vector.
6///
7/// This is an async version of [`std::fs::read`].
8///
9/// This is a convenience function for using [`File::open`] and [`read_to_end`]
10/// with fewer imports and without an intermediate variable. It pre-allocates a
11/// buffer based on the file size when available, so it is generally faster than
12/// reading into a vector created with `Vec::new()`.
13///
14/// This operation is implemented by running the equivalent blocking operation
15/// on a separate thread pool using [`spawn_blocking`].
16///
17/// [`File::open`]: super::File::open
18/// [`read_to_end`]: crate::io::AsyncReadExt::read_to_end
19/// [`spawn_blocking`]: crate::task::spawn_blocking
20///
21/// # Errors
22///
23/// This function will return an error if `path` does not already exist.
24/// Other errors may also be returned according to [`OpenOptions::open`].
25///
26/// [`OpenOptions::open`]: super::OpenOptions::open
27///
28/// It will also return an error if it encounters while reading an error
29/// of a kind other than [`ErrorKind::Interrupted`].
30///
31/// [`ErrorKind::Interrupted`]: std::io::ErrorKind::Interrupted
32///
33/// # io_uring support
34///
35/// On Linux, you can also use io_uring for executing system calls. To enable
36/// io_uring, you need to specify the `--cfg tokio_unstable` flag at compile time,
37/// enable the io-uring cargo feature, and set the `Builder::enable_io_uring`
38/// runtime option.
39///
40/// Support for io_uring is currently experimental, so its behavior may change
41/// or it may be removed in future versions.
42///
43/// # Examples
44///
45/// ```no_run
46/// use tokio::fs;
47/// use std::net::SocketAddr;
48///
49/// #[tokio::main]
50/// async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
51/// let contents = fs::read("address.txt").await?;
52/// let foo: SocketAddr = String::from_utf8_lossy(&contents).parse()?;
53/// Ok(())
54/// }
55/// ```
56pub async fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
57 let path = path.as_ref();
58
59 #[cfg(all(
60 tokio_unstable,
61 feature = "io-uring",
62 feature = "rt",
63 feature = "fs",
64 // libc::statx is only supported on these platforms
65 // FIXME: Add musl target env when our minimum supported
66 // rust version is 1.93. To clarify, statx support is
67 // introduced to musl in 1.25 as mentioned officially here:
68 // https://musl.libc.org/releases.html.
69 // However, rustup target_env building for *-linux-musl
70 // uses 1.25 musl on all *-linux-musl platforms starting
71 // in 1.93 stable rust version.
72 // https://blog.rust-lang.org/2025/12/05/Updating-musl-1.2.5/
73 any(target_env = "gnu", target_os = "android")
74 ))]
75 {
76 use crate::fs::read_uring;
77
78 let handle = crate::runtime::Handle::current();
79 let driver_handle = handle.inner.driver().io();
80 if driver_handle
81 .check_and_init(io_uring::opcode::Read::CODE)
82 .await?
83 {
84 return read_uring(path).await;
85 }
86 }
87
88 read_spawn_blocking(path).await
89}
90
91async fn read_spawn_blocking(path: &Path) -> io::Result<Vec<u8>> {
92 let path = path.to_owned();
93 asyncify(move || std::fs::read(path)).await
94}