How can I write UTF-8 files using JavaScript for Mac Automation?
Asked Answered
I

4

5

In short - what is the JavaScript for Mac Automation equivalent of AppleScript's as «class utf8» ?

I have a unicode string that I'm trying to write to a text file using JavaScript for Mac Automation.

When writing the string to the file, any unicode characters present become question marks in the file (ASCII char 3F).

If this was an AppleScript script instead of a JavaScript one, I could have solved this by adding the as «class utf8» raw statement as explained on Takashi Yoshida's Blog (https://takashiyoshida.org/blog/applescript-write-text-as-utf8-string-to-file/).

The script, however, is already written in JavaScript so I'm looking for the JavaScript equivalent to this AppleScript statement. Apple's page about raw statements addresses only AppleScript (https://developer.apple.com/library/content/documentation/AppleScript/Conceptual/AppleScriptLangGuide/conceptual/ASLR_raw_data.html).

To write the file, I am using Apple's own writeTextToFile JavaScript function example (https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/ReadandWriteFiles.html#//apple_ref/doc/uid/TP40016239-CH58-SW1). I added an as argument to the following call, according to the StandardAdditions dictionary:

// Write the new content to the file
app.write(text, { to: openedFile, startingAt: app.getEof(openedFile), as: "utf8" })

And tried all of the following strings (as written and also in lowercase form):

  • Unicode text
  • Unicode
  • Class utf8
  • «class utf8»
  • utf8
  • text
  • utf8 text

Apart for "text" (which resulted in the same question marks situation), using all of the above strings yielded a zero-bytes file.

I understand I might be wading into uncharted waters here, but if anyone reading this has dealt with this before and is willing to provide some pointers, I will be quite grateful 😋

Idioblast answered 30/5, 2017 at 17:29 Comment(0)
B
7

If you want to ensure your file gets written with UTF8 encoding, use NSString's writeToFile:atomically:encoding:error function, like so:

fileStr = $.NSString.alloc.initWithUTF8String( 'your string here' )
fileStr.writeToFileAtomicallyEncodingError( filePath, true, $.NSUTF8StringEncoding, $() )

You would think that writing an NSString object initialized from a UTF8 string would get written out as UTF8 but I've found from experience that writeToFile:atomically does not honor the encoding of the string being written out. writeToFile:atomically:encoding:error explicitly specifies which encoding to use. On top of that, writeToFile:atomically has been deprecated by Apple since OS X 10.4.

Bohannon answered 31/5, 2017 at 7:59 Comment(0)
U
1

@PatrickWayne has the correct solution.

I already had this function in my lib, so I thought I'd share it. It uses the same key commands.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function writeFile(pPathStr, pOutputStr) {  //  @File @Write @ObjC
  /*  VER: 2.0  2017-03-18  
---------------------------------------------------------------
  PARAMETERS:
    pPathStr    | string  | Path of file to write.  May use tilde (~)
    pOutputStr  |  string  |  String to be output to file.
  */
  
  //--- CONVERT TO NS STRING ---
  var nsStr       = $.NSString.alloc.initWithUTF8String(pOutputStr)
  
  //--- EXPAND TILDE AND CONVERT TO NS PATH ---
  var nsPath      = $(pPathStr).stringByStandardizingPath
  
  //--- WRITE TO FILE ---
  //      Returns true IF successful, ELSE false
  var successBool  = nsStr.writeToFileAtomicallyEncodingError(nsPath, false, $.NSUTF8StringEncoding, null)
  
  if (!successBool) {
    throw new Error("function writeFile ERROR:\nWrite to File FAILED for:\n" + pPathStr)
  }
  
  return successBool
  
};
Uralian answered 31/5, 2017 at 20:11 Comment(0)
I
0

While I was unable to find a way to do it with JavaScript only, I ended up utilizing the Objective-C Bridge to accomplish UTF-8 file write-out.

Here is the code that I used. This is JavaScript code that invokes the Objective-C NSString class, and it replaces the writeTextToFile function that I mentioned above altogether:

objCText = $.NSString.alloc.initWithUTF8String(text);
objCText.writeToFileAtomically(filePathString, true);
Idioblast answered 30/5, 2017 at 17:48 Comment(0)
H
0

JXA can't do symbol types (type and enumerator names) right, and it can't do raw four-char codes at all. Either stick to AppleScript, which is the only officially supported option that speaks Apple events right, or use the Cocoa bridge to write a NSString to file in NSUTF8StringEncoding, c.f. Patrick's solution.

Herbivore answered 31/5, 2017 at 9:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.