Repository navigation
fread should un-escape escaped quotes in fields #1109
Description
Activity
- changed the title
[-]fread double quote in character columns[/-][+]fread double quote in character columns, needs 'allowEscapes' like argument[/+]on Sep 8, 2015 PS: Remember to also test and credit #1299.
MOVED from #1299
I do as well have problems with the wayfreadcurrently handles quotes and tried to find a solution (don't look at my fork - it's sh*t).
Here are my thoughts on it:There are two more or less separate issues:
Quoting
Some strings contain control characters (wrt a csv file) like
\n,\lor sep (eg.,).
To allow unambiguous parsing of files containing such characters such strings must be quoted, i.e. surrounded by a quote character(typically").
Quote charters, however, may be part of a sting as well:He said: "What'up?"or{"id": 34, "character":"\""}
There are two major strategies to escape them:- Double: all quote characters inside the string to be quoted get repeated once. e.g. the above would become
"He said: ""What'up?"""and"{""id"": 34, ""character"":""\""""}"' - Escape character: all quotes inside the string to be quoted get escaped by a preceding escape character (usually
\). With this method the escape character must be escaped as well if it was part of the string before (usually now using the Double method). e.g. the above strings would become"He said: \"What'up?\""and"{\"id\": 34, \"character\":\"\\\"\"}"
The former is easier to implement and uses less extra storage. The latter is the standard for
write.table. Howeverwrite.tablefails to implement the second part and does not escape\if it was part of the string. This leads to problems e.g. in the following case (in the 7th line, the quoted region never ends):> a = "\\write.table \"killer\"\\"; a [1] "\\write.table \"killer\"\\" > cat(a) \write.table "killer"\ > write.table(a) "x" "1" "\write.table \"killer\"\" > write.table(a, qmethod = "double") "x" "1" "\write.table ""killer""\"Note that quoting always comes with a quote escape method. If the quoted string did not contain any quoting characters, using non escaping quoting would be equivalent to using the double escaping method. If It did also not contain the escape character, escape character escaping quoting would be equivalent as well. Often it is possible to infer the quote escape method used.
I would want
freadto correctly parse csv files if the user specifies the used quote method on a per file basis. Whereqmethodcould be either something like:"notQuoted"allowing to read files that contain fields with arbitrarily many"but no control characters (e.g. this real world example)"quotedDoubleEscaped""quotedEscapeCharEscaped"
It would be cool if one could specify the quote and the escape character.
Further I would want fread to deduce the quote method if possible.
Unquoting
i.e. the removal of the leading and trailing quote charactars from the string and the unescaping of the string
freadshould do this only if all fields of one column are exactly one quoted region (necessarily but not sufficiently begin and end with a quote) or if sep2 was implemented if the same holds for all sub-fields of a column.
There should be options to specify unquoting behavior on a per column basis.
At leastfreadshould provide easy ways to do unquoting afterwards.Summary
Reading files with escaped quotes (as specified by the user) is a must.
freadshould try to deduce the quote escaping method used.
It would be cool if fread would allow for unquoting and even cooler if it would try to guess what should be unquoted.For ease of writing/reading these words sound much more confident than I am about them. I don't want to nag but to help.
best,
JanPS: some example of currently improperly handled data:
> a = '"gene names" "protein names"\nABL,JTK7 "Abelson murine leukemia viral oncogene homolog 1","Abelson tyrosine-protein kinase 1"'; cat(a) "gene names" "protein names" ABL,JTK7 "Abelson murine leukemia viral oncogene homolog 1","Abelson tyrosine-protein kinase 1" > fread(a) gene names protein names 1: ABL,JTK7 Abelson murine leukemia viral oncogene homolog 1","Abelson tyrosine-protein kinase 1 > fread(a,quote = "") Empty data.table (0 rows) of 3 cols: ABL,JTK7 "Abelson murine leukemia viral oncogene homolog 1","Abelson tyrosine-protein kinase 1" Warning message: In fread(a, quote = "") : Starting data input on line 2 and discarded previous non-empty line: "gene names" "protein names"Reacted by kam-l-ko- Double: all quote characters inside the string to be quoted get repeated once. e.g. the above would become
I think my problem should be added to this, as it relates to allowing escapes and a feature request in the Master task for
freadbugs. I'm using the 1.10.4-3 of data.table.When exporting using the default
fwritesettings, quotes inside of quotes are doubled to escape. Here is a line of the csv, showing that in the name'Oller, Thomas "Rico"', the quotes are doubled to escape it and also balanced correctly :AD04,19992000,"Oller, Thomas ""Rico""",A,Oller,Thomas,Oller,,,Assemblymember,Assemblymember,REP,Y,LEG_ESI,2006-12-15 12:43:44,NHowever, when using
fread, these are not handled well. The result is double quotes:Oller, Thomas ""Rico""Its only when I use the read.csv that this is read correctly as:
Oller, Thomas "Rico"Note that this problem persists when forcing quotes, with
quote=TRUEinfwrite. I also get strange triple slashes when settingfwritetoquote=TRUE, qmethod='escape'. In fact, I haven't found a way to simply import and export using thefread/fwritecombination! I only can import it back usingdata.table(read.csv(...)). Since i haven't found a simple solution using data.table to a simple task, this feels like a big bug!Reacted by Valentas, Mārtiņš Liberts and kam-l-koEscapes are defined this standard, RFC 4180:
https://tools.ietf.org/html/rfc4180#page-6Here is a one line example of the issue:
fread('AD04,19992000,"Oller, Thomas ""Rico""",A,Oller,Thomas,Oller,,,Assemblymember,Assemblymember,REP,Y,LEG_ESI,2006-12-15 12:43:44,N\n')The example shows that
freaddoes not handle escapes the way the standard defines them, as the quotes around "Rico" are not escaped:V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 1: AD04 19992000 Oller, Thomas ""Rico"" A Oller Thomas Oller NA NA Assemblymember Assemblymember REP Y LEG_ESI V15 V16 1: 2006-12-15 12:43:44 NReacted by Adam Hoelscher, ASA, MAAAIf fread does not comply with RFC 4180 for .csv, then why not escalate that to a 'Bug'?
- changed the title
[-]fread double quote in character columns, needs 'allowEscapes' like argument[/-][+]fread should un-escape escaped quotes in fields[/+]on Dec 15, 2017 - modified the milestones: This milestone has been deleted, This milestone has been deleted
on Dec 15, 2017 Just got bit by this... a bit unfortunate that
fwritedefault become hard to invert...Escaping " using "" (qmethod="double") is the only option for tables exported in BigQuery.
I just got bit by this as well. I would expect
fwritefollowed byfreaddefault parameters to recover the data.Example snippet:
library(data.table) dt <- data.table( id = 1L, text = 'My name is John "Bower" Nichols' ) f <- tempfile(fileext = ".csv") fwrite(dt, f) # No change with quote = "auto", qmethod = "double" dt2 <- fread(f) dt$text dt2$text identical(dt$text, dt2$text) dt dt2> dt$text [1] "My name is John \"Bower\" Nichols" > dt2$text [1] "My name is John \"\"Bower\"\" Nichols" > identical(dt$text, dt2$text) [1] FALSE > dt id text <int> <char> 1: 1 My name is John "Bower" Nichols > dt2 id text <int> <char> 1: 1 My name is John ""Bower"" Nicholsdata.table 1.18.2.1
Reacted by kam-l-ko- added 2 commits that reference this issue
on Aug 6, 2026
According to the docs:
The following csv should be supported by
fread.Findings:
as of now, only writing using
qmethod="double"andread.tablecorrectly supports write-read such kind of data.Latest dev data.table, my locale, etc: