From murdoch.duncan at gmail.com  Wed May  3 19:21:58 2017
From: murdoch.duncan at gmail.com (Duncan Murdoch)
Date: Wed, 3 May 2017 13:21:58 -0400
Subject: [Rd] Any progress on write.csv fileEncoding for UTF-16 and
 UTF-32 ?
In-Reply-To: <ee4a023a-2f5c-0c48-345a-fbcc20bee980@gmail.com>
References: <000101d2c143$bd644380$382cca80$@bigpond.com>
 <6dee41ed-b1c1-4d4d-0eb1-03f3e7e0d759@gmail.com>
 <9dce0e1b-27d8-60ca-9df3-3227aab0a3f8@gmail.com>
 <000001d2c2dd$f4aa2d00$ddfe8700$@bigpond.com>
 <ee4a023a-2f5c-0c48-345a-fbcc20bee980@gmail.com>
Message-ID: <b8eaa2ab-6630-cf62-d9ef-fbb33422b244@gmail.com>

Now fixed in R-devel revision 72650.

Duncan Murdoch

On 02/05/2017 4:11 AM, Duncan Murdoch wrote:
> On 01/05/2017 8:49 PM, Jack Kelley wrote:
>> Thanks for looking into this.
>>
>> A few notes regarding all the UTF encodings on Windows 10 ...
>
> This all stems from the ancient bad decision by Microsoft to translate
> LF characters to CR LF when writing text files.  R passes 0A or 0A 00 or
> 0A 00 00 00 to the output routine (part of the C run-time), and it needs
> to figure out how many characters there are in those bytes in order to
> add the appropriate CR with the right width.
>
> The default is 8 bit, so you get 0D 0A in current versions of R,
> regardless of the encoding.
>
> There are ways to declare UTF-16LE (see
> https://msdn.microsoft.com/en-us/library/yeby3zcb.aspx, or Google
> "Windows fopen" if that moves), but no other wide encoding.  That's what
> I'm putting in place if you ask for UTF-16LE or UCS-2LE.  So far I'm not
> planning to handle UTF-16BE or UTF-32, because doing those would mean R
> would have to handle the translation of LF itself, and I'm too lazy to
> do that.
>
> So far this is working for writes, but not reads.  I still have to track
> down what's going wrong there.
>
> Duncan Murdoch
>
>>
>> The default eol for write.csv (via write.table) is "\n" and always gives
>> as.raw (c (0x0d, 0x0a)), that is, <Carriage Return> <Line Feed> as adjacent
>> bytes. This is fine for UTF-8 but wrong for UTF-16 and UTF-32.
>>
>> EXAMPLE: Using UTF-32 for exaggeration (note also that 3 nul bytes are
>> missing in the final CR+LF):
>>
>> df <- data.frame (x = 1:2, y = 3:4)
>>
>> $`UTF-32LE`$default.eol$raw
>>  [1] 22 00 00 00 78 00 00 00 22 00 00 00 2c 00 00 00 22 00 00 00 79 00 00 00
>> 22
>> [26] 00 00 00 0d 0a 00 00 00 31 00 00 00 2c 00 00 00 33 00 00 00 0d 0a 00 00
>> 00
>> [51] 32 00 00 00 2c 00 00 00 34 00 00 00 0d 0a 00 00 00
>>
>> $`UTF-32BE`$default.eol$raw
>>  [1] 00 00 00 22 00 00 00 78 00 00 00 22 00 00 00 2c 00 00 00 22 00 00 00 79
>> 00
>> [26] 00 00 22 00 00 00 0d 0a 00 00 00 31 00 00 00 2c 00 00 00 33 00 00 00 0d
>> 0a
>> [51] 00 00 00 32 00 00 00 2c 00 00 00 34 00 00 00 0d 0a
>>
>> (Nevertheless, Microsoft Excel 2013 tolerates these CSVs!)
>>
>> One trick/solution is to use eol = "\r" (that is, <Carriage Return> only).
>>
>> Regards -- Jack Kelley
>>
>> ----------------------------------------------------------------------------
>> --------
>>
>> remove (list = objects())
>> print (sessionInfo())
>> cat ("##########################################################\n\n")
>>
>> ENCODING <- c (
>>   "UTF-8",
>>   "UTF-16LE", "UTF-16BE", "UTF-16",
>>   "UTF-32LE", "UTF-32BE", "UTF-32"
>> )
>>
>> df <- data.frame (x = 1:2, y = 3:4)
>>
>> csv <- structure (lapply (ENCODING, function (encoding) {
>>   csv <- sprintf ("df_%s.csv", encoding)
>>   write.csv (df, csv, fileEncoding = encoding, row.names = FALSE)
>>   list (default.eol = list (
>>     csv = csv, raw = readBin (csv, "raw", 1000))
>>   )
>> }), .Names = ENCODING)
>>
>> EOL <- c (LF = "\n", CR = "\r", "CR+LF" = "\r\n")
>>
>> CSV <- structure (lapply (ENCODING, function (encoding) {
>>   structure (
>>     lapply (names (EOL), function (EOL.name) {
>>       csv <- sprintf ("df_%s_eol=%s.csv", encoding, EOL.name)
>>       write.csv (
>>         df, csv, fileEncoding = encoding, row.names = FALSE,
>>         eol = EOL [EOL.name]
>>       )
>>       list (csv = csv, raw = readBin (csv, "raw", 1000))
>>   }), .Names = names (EOL))
>> }), .Names = ENCODING)
>>
>> print (csv)
>> print (CSV)
>>
>> ----------------------------------------------------------------------------
>> ----------------
>>
>> -----Original Message-----
>> From: Duncan Murdoch [mailto:murdoch.duncan at gmail.com]
>> Sent: Tuesday, 2 May 2017 04:22
>> To: Jack Kelley <Jack.Kelley at bigpond.com>; r-devel at r-project.org
>> Subject: Re: [Rd] Any progress on write.csv fileEncoding for UTF-16 and
>> UTF-32 ?
>>
>> On 30/04/2017 12:23 PM, Duncan Murdoch wrote:
>>> No, I don't think anyone is working on this.
>>>
>>> There's a fairly simple workaround for the UTF-16 and UTF-32 iconv
>>> issues:  don't attempt to produce character vectors, produce raw vectors
>>> instead. (The "toRaw" argument to iconv() asks for this.) Raw vectors
>>> can contain embedded nulls.  Character vectors can't, because
>>> internally, R is using 8 bit C strings, and the nulls are string
>>> terminators.
>>>
>>> I don't know how difficult it would be to fix the write.table problems.
>>
>> I've now taken a look, and it appears as if it's not too hard.  I'll see
>> if I can work out a patch that I trust.
>>
>> Duncan Murdoch
>>
>>>
>>> Duncan Murdoch
>>>
>>> On 29/04/2017 7:53 PM, Jack Kelley wrote:
>>>> "R version 3.4.0 (2017-04-21)"  on "x86_64-w64-mingw32" platform
>>>> ... [rest omitted]
>>
>>
>



[Rd] Any progress on write.csv fileEncoding for UTF-16 and UTF-32 ?
Duncan Murdoch