Skip to main content

Reader

Struct Reader 

Source
pub struct Reader<R: Read> { /* private fields */ }
Expand description

A pull-based CSV reader that parses records from any Read source.

The reader supports both in-memory slices (&[u8]) and streaming I/O sources (std::io::Read) via the custom Read trait. Rows are parsed on-demand by calling rows or rows_bytes.

§Configuration

Use builder methods for a fluent setup:

§Headers

Call parse_headers to treat the first row as column names. After doing so, headers returns a Some slice and serde deserialization (with the serde feature) can match by field name.

§Errors

Parsing errors (unterminated quotes, trailing content after a quoted field, inconsistent field counts) are stored on the returned row and surfaced when the row’s fields are accessed. I/O errors are also stored on the row. This allows iteration to continue past malformed rows: when a record is malformed, the reader skips to the next record boundary before parsing the following record.

Errors are reported against the line on which the offending record started.

§Resource limits

By default the reader imposes no size limits, so a single enormous record can consume an unbounded amount of memory. Applications that parse untrusted input should set set_max_record_bytes (and optionally set_max_field_bytes / set_max_columns); exceeding a limit produces an error on the row instead of exhausting memory.

§Iteration

Produces owned Row or BytesRow values. A Row validates UTF-8 on field access; BytesRow does not. Rows can outlive the reader.

§Examples

use csv::Reader;

let data = b"name,age\nAlice,30\nBob,25\n";
let mut reader = Reader::new(&data[..]);

// Parse the first row as headers.
let headers = reader.parse_headers().unwrap();
assert_eq!(headers, &["name", "age"]);

// Iterate over data rows.
for row in reader.rows() {
    for field in row.iter() {
        let _: &str = field.unwrap();
    }
}
let file = std::fs::File::open("data.csv").unwrap();
let mut reader = Reader::new(file).set_delimiter(b';');

for row in reader.rows() {
    let name = row.get(0).unwrap().unwrap();
    println!("{name}");
}

Implementations§

Source§

impl<R: Read> Reader<R>

Source

pub fn new(source: R) -> Self

Creates a new Reader from any Read source.

This works with &[u8], std::io::Cursor, std::fs::File, etc.

Source

pub fn set_delimiter(self, byte: u8) -> Self

Sets the field delimiter byte (default is ,).

§Panics

Panics if byte is ", \r or \n. These bytes carry structural meaning in CSV and cannot be used as a delimiter: " would disable quoting, and \r/\n would make record boundaries unrepresentable, causing the whole input to be read as a single record.

Source

pub fn set_flexible(self, yes: bool) -> Self

Sets whether variable field counts are allowed (default is false).

Source

pub fn set_strip_bom(self, yes: bool) -> Self

Controls whether a UTF-8 byte-order mark (U+FEFF, the bytes EF BB BF) at the very start of the input is skipped (default is true).

This is what makes files produced by Excel, which writes UTF-8 CSV with a BOM by default, work with parse_headers and serde: without it the first header would be "\u{feff}name" and would match no struct field.

Only the first three bytes of the stream are considered, and only once. A BOM anywhere else in the input is always treated as data.

Pass false to keep the mark as part of the first field.

Source

pub fn set_max_record_bytes(self, max: usize) -> Self

Rejects any record longer than max bytes.

This is the main defence against a single crafted record exhausting memory. When a record exceeds the limit the row carries a ReadErrorKind::RecordTooLarge error and reading stops, because the remainder of the oversized record cannot be skipped safely.

By default no limit is applied.

Source

pub fn set_max_field_bytes(self, max: usize) -> Self

Rejects any field longer than max bytes.

When a field exceeds the limit the row carries a ReadErrorKind::FieldTooLarge error and reading stops, because the remainder of the oversized record cannot be skipped without reading it.

By default no limit is applied.

Source

pub fn set_max_columns(self, max: usize) -> Self

Rejects any record with more than max columns.

Each column costs at least one byte of input, so this is a cheap way to bound the bookkeeping memory used by a record made of millions of empty fields. When a record exceeds the limit the row carries a ReadErrorKind::TooManyColumns error and reading stops, because the remainder of the oversized record cannot be skipped without reading it.

By default no limit is applied.

Source

pub fn set_headers(self, headers: Vec<String>) -> Self

Sets the column names for header-based serde deserialization.

Calling this marks headers as parsed so reader.headers() returns Some, and pins the expected field count to the number of names supplied (unless set_flexible is enabled), exactly like parse_headers.

Source

pub fn headers(&self) -> Option<&[String]>

Returns Some(&[String]) if headers were parsed or set, None otherwise.

Source

pub fn parse_headers(&mut self) -> Result<&[String], ReadError>

Parses the first row as column headers and stores them internally.

Returns the header strings as a slice, and pins the expected field count to the number of headers (unless set_flexible is enabled).

If the input is empty this returns an empty slice and leaves headers as None, since no header row was seen.

Source

pub fn rows(&mut self) -> Rows<'_, R> ⓘ

Returns an iterator over Row values (validated as UTF-8).

Source

pub fn rows_bytes(&mut self) -> BytesRows<'_, R> ⓘ

Returns an iterator over BytesRow values (no UTF-8 validation).

Auto Trait Implementations§

§

impl<R> Freeze for Reader<R>
where R: Freeze,

§

impl<R> RefUnwindSafe for Reader<R>
where R: RefUnwindSafe,

§

impl<R> Send for Reader<R>
where R: Send,

§

impl<R> Sync for Reader<R>
where R: Sync,

§

impl<R> Unpin for Reader<R>
where R: Unpin,

§

impl<R> UnsafeUnpin for Reader<R>
where R: UnsafeUnpin,

§

impl<R> UnwindSafe for Reader<R>
where R: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.