Skip to main content

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}