Pure inference, no side effects: inspects a delivery file and returns what a config would need – format, encoding, delimiter/quote, header presence, column names (with duplicate header names renamed positionally), per-column types, and key-column candidates – as a plain list. This is the detection half of the config generator; the writer turns it into a commented YAML.
Value
A named list: path, format ("csv"/"fwf"),
encoding, encoding_valid_utf8, encoding_guess,
bom, delimiter, quote_char, header,
csv_skip, col_names, renamed_from (new name ->
original, NULL unless duplicates were renamed), fwf_widths,
fwf_col_names, fwf_packed, column_types,
key_column_candidates, expected_columns,
n_sample_rows, provenance.
Details
Encoding uses the same full-file streamed scan as read_dataset()
(scan_file_encoding()): a file that is not valid UTF-8 gets the same
single-byte fallback the reader would use, recorded in
encoding_guess. Types come from infer_col_type – the
one implementation, so the sniff can never disagree with run-time
classification. Structure detection reads a bounded head sample
(n_sample_rows reports how many data rows informed it), never the
file body.
Fixed-width files: when the sampled lines are all the same width and no
delimiter splits them, boundaries are guessed with
readr::fwf_empty() (blank-gutter detection). A packed file (no
blank gutters) sets fwf_packed = TRUE and fwf_widths = NULL
rather than guessing wrongly – the generator emits a TODO the
validator refuses to run.
Every headline field's origin is recorded in provenance
("detected", "default", or "generated"), so the
writer can emit detected values live and defaults commented out.
Examples
f <- tempfile(fileext = ".csv")
writeLines(c("id,amount", "A1,10", "A2,20"), f)
s <- sniff_dataset(f)
s$format; s$col_names; s$column_types
#> [1] "csv"
#> [1] "id" "amount"
#> id amount
#> "character" "numeric"