最初は、テキストファイル全体を文字列に読み込む方法を紹介します。
以下はchoose file命令を使ってファイルをユーザーに選択してもらって、テキストを読み込むスクリプトです。
set theText to loadText(choose file)
on loadText(theFile)
try
open for access theFile
set theText to read theFile
on error
end try
close access theFile
return theText
end loadText
ファイルの入出力ではエラーが発生しやすく、いちいち全部チェックしていたらスクリプトが先に進みませんが、Tryブロックで括って、最低限close access命令でファイルを閉じることだけはやっておきます。
read命令は、多くの引数を持ちますが、何も指定しない場合は「ファイル全体を文字列として」読み込みます。
ファイル全体を読み込むのならば、openやcloseなどを省いて、いきなりread命令を書けば、自動的にopenやclose処理も行ってくれます。
set theText to read (choose file)
全体を読み込まなくても、1行読めば事足りることもあります。
以下は、一行だけ読み込むハンドラです。before returnというオプションが、改行文字を区切りにして、区切りの直前まで読み込む事を意味します。ちなみに、beforeの代わりにuntilを使うと区切り文字も含まれます。区切り文字は任意の文字一文字です。
read1Line(choose file of type {"TEXT"})
on read1Line(theFile)
try
open for access theFile
set textData to read theFile before return
on error
end try
close access theFile
return textData
end read1Line
頭から数行読みたい場合は、連続してread命令を実行すると文字列も連続的に読み込まれます。
もし、指定した行数がテキストファイルに存在していなかった場合はエラーが発生しますが、tryでトラップされるので、問題なくハンドラから値が返ってきます。
以下は、指定した行数を読み込むハンドラです。
readSomeLines(choose file of type {"TEXT"}, 10)
on readSomeLines(theFile, theLine)
set textData to ""
try
open for access theFile
repeat theLine times
set textData to textData & (read theFile until return)
end repeat
on error
end try
close access theFile
return textData
end readSomeLines
残念ながら、区切り文字は一つしか設定できないので、タブと改行で区切られた文字列などは一度に処理する事はできません。
たとえば、改行までの文字を読み込み、「文字列の検索・置換」で解説したtext item delimitersを利用した方法で、さらにタブで分割するという方法を取る事になります。
repeatの部分が永久ループになっていますが、ファイルの最後を超えて読もうとしたときににエラーがでるので、それをtryでトラップする事で終了しています。エラーを積極的に利用するのは、なにも悪い事ではありません。
ついでに、「引数の参照渡し」で説明した方法で、xListの値をハンドラの中で書き換えているので、特にハンドラから値を返さなくても、ちゃんとxListに、分割された文字列のリストが入っている事を確認できると思います。
set xList to {}
devTabRet(choose file of type {"TEXT"}, xList)
xList
on devTabRet(theFile, theList)
set tmp to text item delimiters
set text item delimiters to tab
try
open for access theFile
repeat
set end of theList to every text item of (read theFile before return)
end repeat
on error
end try
close access theFile
set text item delimiters to tmp
end devTabRet
先ほどのようなテキストを読み込むには、実はもっと簡単な方法があります。しかも、かなり高速です。
具体的にはread命令のusing delimitersオプションを使います。このオプションには複数の区切り文字が指定できます。
以下は、先ほどとは少し違い、二重のリストではなく、タブと改行の区別なく単一のリストにします。
また、リストは結果として返します。これは単に書き方の問題とも言えますが、大量のデータを扱う場合はrefで参照渡ししてcontents ofで代入した方が、なにかといいでしょう。
devTabRet(choose file of type {"TEXT"})
on devTabRet(theFile)
try
open for access theFile
set theList to read theFile using delimiters {tab,return} as string
on error
end try
close access theFile
return theList
end devTabRet
asオプションでinteger等を指定すると、リストにする際に文字列からの型変換を行います。当然ですが、文字列から変換できるクラスを指定する必要があります。
具体的にはread命令のbefore(until)とusing delimitersオプションは併用できるので、別の使い方もできます。
以下は(1)でのハンドラと同じ働きをします(正確には、空行の出力が(1)は{""}、(3)は{}という違いがあります)
set xList to {}
devTabRet(choose file of type {"TEXT"}, xList)
xList
on devTabRet(theFile, theList)
try
open for access theFile
repeat
set end of theList to (read theFile before return using delimiters {tab} as string)
end repeat
on error
end try
close access theFile
end devTabRet
このあたりが、テキストファイルを読み込む場合の基本的な方法と言えるでしょう。
ちなみに、きちんと最後まで読み込んでエラーとなったのか、その他のエラーになったのかきっちり分けたい場合、-39が最後まで読んだ場合にでるエラーなので、on errorブロックでチェックしておけばいいでしょう。