« JavaScript for Automation (JXA)でフォルダアクション | トップページ | JavaScript for Automation (JXA)でファイルをFTPアップロード »

2018年2月15日 (木)

JavaScript for Automation (JXA)でUTF-8テキストの読み書き

Apple Script 同様、JXA でも本来の機能を用いてテキストを開いて読み書きすることはできる。

app = Application.currentApplication();
app.includeStandardAdditions = true;
app.openForAccess(item_1);
var text_content = app.read(item_1, {as:"text"});
app.closeAccess(item_1);

しかしこれでは、文字コードが MacOS(Shift JIS の Mac 独自仕様)になり、改行コードも CR に変わってしまうため、筆者のように外国語と日本語が混じった文章を書く人間にとっては実用的ではない。

そのため、unicode テキストを扱うには JXA でもやはり doShellScirpt 頼みということになる。

"quoted form of" の代替

まず前提として、コマンドラインプログラムを呼び出す場合、変数に格納されている文字列にクォーテーションマークが含まれている場合の処理が問題になる。

Apple Script では quoted form of という便利なものがあったが、JXA では実装されていない。

その代わり、コマンドラインに含める変数(下記の例では item_1Path)に、.replace(/\'/g, "'\\''") をつけることでエスケープできる(表記の都合上、バックスラッシュが全角になっているが実際には半角である)

var item_1Path = "/Users/xxxxx/foo/bar/hogehoge.txt";
var text_content = app.doShellScript("cat '"+item_1Path.replace(/\'/g, "'\\''")+"'" , {alteringLineEndings:false})

推測だが、このように簡単に回避できるので、あえて quoted form of を実装していないのだろうと思う。

テキストを読み込む

ここからが本題。

app = Application.currentApplication();
app.includeStandardAdditions = true;
var item_1Path = "/Users/xxxxx/foo/bar/hogehoge.txt";
var text_content = app.doShellScript("cat '"+item_1Path.replace(/\'/g, "'\\''")+"'" , {alteringLineEndings:false})

, {alteringLineEndings:false} は必須。これがないと、改行コードが CR に置き換わってしまう。コマンドラインでテキストを読み込む場合、変数に格納する際には {alteringLineEndings:false} が常に必要である(なんらかの理由で敢えて CR 化したいという場合は除く)。

それと


app = Application.currentApplication();
app.includeStandardAdditions = true;

も必須である。

テキストを書き込む

app = Application.currentApplication();
app.includeStandardAdditions = true;
var writePath = "/Users/xxxxx/foo/bar/output.txt";
app.doShellScript("/bin/echo -n '"+text_content.replace(/\'/g, "'\\''")+"' > '"+writePath.replace(/\'/g, "'\\''")+"'")


text_content が書き込まれる内容である。シングルクオートが含まれている可能性があるのでやはり .replace(/\'/g, "\\''") をつけている。

なお、こちらは , {alteringLineEndings:false} は必要ない(変数に格納しないので)。


いずれの場合も、パスにスペースが含まれている場合(例えば /Users/xxxxx/Documents/My Favorite Aqours Song Lyrics/君のこころは輝いてるかい?.txt など)に備えてシングルクォーテーションマーク ' でパスを囲んでいる。

パスに絶対スペースが含まれない自信があるなら、囲む必要はない。クォーテーションマーク(ダブル、シングルとも)が絶対含まれないなら、.replace(/\'/g, "'\\''")をつける必要もない。

var text_content = app.doShellScript("cat "+item_1Path , {alteringLineEndings:false})

書き込みの場合のテキストも同様。

app.doShellScript("/bin/echo -n "+text_content+" > "+writePath)

原則論としては、うっかりスペースやクォーテーションを含んだパスやテキストを処理してしまう可能性があるため、つけておくのが無難だと思う。


« JavaScript for Automation (JXA)でフォルダアクション | トップページ | JavaScript for Automation (JXA)でファイルをFTPアップロード »

コメント

コメントを書く

(ウェブ上には掲載しません)

« JavaScript for Automation (JXA)でフォルダアクション | トップページ | JavaScript for Automation (JXA)でファイルをFTPアップロード »