Handling Multibyte Characters and Strings in R: Fixing CSV Encoding Errors

Illustrated infographic summarizing: Handling Multibyte Characters And Strings In R Project

By Greg Nowak. Last updated 2026-09-06.

A CSV import can look fine until tolower() fails with an “invalid multibyte string” error. For a team preparing customer records, product feeds or agency reports, that can interrupt a routine delivery. A hurried fix can also remove meaningful characters from the data.

The practical approach is to identify the source encoding, read the file correctly and check representative records before continuing. Danish letters such as æ, ø and å belong in customer names and addresses. They should survive the import.

The earlier version of this article suggested switching from UTF-8 to Latin-1 and removing non-ASCII characters. Both techniques have specific uses, but neither is a general repair for broken text.

What causes multibyte string errors in R?

An encoding defines how bytes represent text. In UTF-8, a character may occupy several bytes. Problems arise when R interprets those bytes using an incompatible encoding, or when the input contains damaged or mixed text.

Start with the export settings of the system that produced the CSV. Ask for its declared encoding and keep an untouched copy of the file. Changing an import setting until the error disappears is insufficient evidence that the text is correct.

Choose the next step from the symptom, then verify it against the original data.
Symptom What to investigate Practical next step
Names look wrong immediately after import The file may have been decoded incorrectly Confirm the export encoding and reimport the original file
tolower() fails on some records Invalid bytes or inconsistent encoding Isolate affected values and inspect their source
Only certain supplier files fail Different export settings across suppliers Define an import configuration for each source
A destination requires ASCII An explicit restriction on permitted characters Create a separate export field and review the information lost

Read the CSV with its actual encoding

In base R, fileEncoding specifies the file’s encoding and enables conversion during import. The similarly named encoding argument marks strings; it does not re-encode the input. That distinction is documented in R’s data import reference.

# Use the encoding confirmed by the exporting system.
source_encoding <- "UTF-8"  # Change to "latin1" only if confirmed.

df <- read.csv(
  "customers.csv",
  fileEncoding = source_encoding,
  colClasses = "character"
)

Reading columns as text during diagnosis helps preserve identifiers with leading zeros. Convert numeric and date columns deliberately afterwards. For semicolon-separated files with decimal commas, use read.csv2().

Base R’s file conversion targets the current locale, which can limit the characters it represents. If your project uses readr, its import functions produce UTF-8 strings and let you specify the source encoding explicitly:

df <- readr::read_csv(
  "customers.csv",
  locale = readr::locale(encoding = source_encoding),
  col_types = readr::cols(.default = readr::col_character())
)

If the encoding is undocumented, readr::guess_encoding("customers.csv") can suggest candidates. Treat these as clues: the readr locale documentation shows that a plausible guess can still produce incorrect letters. Compare imported names and punctuation with known originals. If the exporter specifies Windows-1252, use that explicitly rather than assuming it is identical to Latin-1.

Convert existing strings without hiding failures

Encoding(text) reports declared encodings, not a reliable detection of the original file format. A result of "unknown" does not automatically mean damaged text; ASCII strings are normally unmarked. Assigning Encoding(text) <- "UTF-8" changes the declaration without converting the bytes. See R’s encoding reference.

If a character vector still contains bytes in a known source encoding, use iconv(). This small example deliberately constructs a Latin-1 name:

text <- c("S\xf8ren", NA_character_)
converted <- iconv(text, from = "latin1", to = "UTF-8", sub = NA)

failed <- which(!is.na(text) & is.na(converted))
if (length(failed) > 0L) {
  stop("Encoding conversion failed; review the original values.")
}

This distinguishes conversion failures from values that were already missing. Avoid sub = "" during diagnosis because it discards unconvertible bytes. Conversion behaviour varies across platforms, and a successful conversion does not prove the source encoding was correct. Those limitations are covered in R’s iconv documentation.

Do not apply a Latin-1 conversion to data already correctly imported as UTF-8. When the earlier import is suspect, return to the original file.

Apply lowercase conversion after fixing the input

Once the text is correctly decoded, create a separate field such as df$customer_name_lower <- tolower(df$customer_name). Preserve the original name for display and review.

Case conversion depends on the platform and locale, as R’s case conversion documentation explains. Check examples from the languages you actually process on the machine running the scheduled job. A lowercase name alone should not become a customer identifier.

When the original gsub command is appropriate

The original command remains useful when a destination explicitly accepts only printable ASCII:

ascii_text <- gsub('[^\x20-\x7E]', '', text)

Run it on correctly decoded text and keep the result separate. It removes everything outside ASCII space through tilde, including accented letters, emoji, tabs and line breaks. “Søren” becomes “Sren”. It deletes characters rather than transliterating them, so it is unsuitable as routine cleanup for names or addresses.

Make the fix part of the workflow

Before accepting an import, reconcile record counts, inspect warnings, compare missing values and check a small sample containing international characters. Keep those examples as repeatable checks for the next export. Document the source encoding, delimiter and person responsible for resolving failures.

If recurring CSV problems are delaying reporting or client delivery, talk to Greg about the import workflow. Bring the failing command, export settings and an anonymised sample that preserves the problematic bytes. That gives the investigation a concrete starting point.

Related on GrN.dk

Need help with this kind of work?

Talk to Greg about your data import workflow Get in touch with Greg.

Sources

Seneste artikler

Brug AI til webshoppens alt-tekster med en overskuelig pilot: kortlæg billederne, få danske forslag, og kontrollér resultatet i WordPress og WooCommerce.

AI-baseret ticketanalyse kan afsløre gentagne klager, produktfejl og huller i dokumentationen – uden at virksomheden behøver endnu en chatbot.

OpenSSH 10 fjerner DSA og advarer om nøgleudveksling, der ikke er post-kvantesikker. Her får du en metode til at afgrænse SFTP-oprydningen uden at svække alle SSH-forbindelser.

Botforespørgsler overstiger nu menneskelig webtrafik. Lær at auditere AI-crawlere, fastsætte regler på stiniveau, håndhæve robots.txt og måle det forretningsmæssige afkast.

Cloudflares Tunnel-opdateringer fra 2026 forbedrer kortlægning, overvågning af replikaer, logstreaming og overdragelse – men synliggør samtidig svagt ejerskab og mangelfuld praksis for failover og logging.

Sådan bruger du AI til mødenoter og opfølgning, mens faste regler beskytter CRM-data, kundematch og pipeline mod fejl og forhastede ændringer.

Drupal 10 når end of life den 9. december 2026. Brug denne praktiske kortlægning til at afgrænse arbejdet med Drupal 11-parathed, Composer-efterslæb, moduler og custom code.

Apache 2.4.67 tydeliggjorde risikoen ved overtagne reverse proxies. Læs, hvordan du opgraderer til 2.4.68, gennemgår HTTP/2, AJP og .htaccess og tester ændringerne sikkert.

WooCommerce-blokke er standarden, men ikke alle webshops er klar. Brug denne praktiske gennemgang, testplan og rollback-procedure til at beskytte omsætningen i checkout.

Cloudflare Service Keys holder op med at virke den 30. september 2026. Find ældre scripts, vælg API-tokens med afgrænsede rettigheder, test overgangen, og dokumentér ejerskabet.

Anmeld Greg på Google

Greg Nowak Google-anmeldelser

 

Skriftlige anbefalinger fra Trafik og Veje, Aarhus Kommune (2011) og AgroTech (2010) — læs dem på LinkedIn.