プログラム講座 初級編12
- MacからUNIXへの改行コード変換 -
初級編12です。今回は「MacからUNIXへの改行コード変換」を行います。なぜMacからWin (MS-DOS)ではないのかというと、これは練習台(?)だからです。メモリから読み込んで書き込みを行い、最後にファイル出力を行うといった処理をします。これができればテキストファイルだけでなく、全てのファイル内容を変更し書き出すと言った高速処理を行う事ができます。今回は初級編9〜11までの続きになっています。
◆改行コード
異機種であってもテキストファイルくらいは互換性がありそうですが、実際はコードの違いで正しく読めない場合が多々あります。
機種 | 日本語コード | 改行コード |
Macintosh | Shift JIS | 13 (CR) |
MS-DOS/Windows | Shift JIS | 13,10 (CR+LF) |
UNIX | JIS, EUC | 10 (LF) |
- CR = Carriage Return
- LF = Line Feed
実際は同じShift JISであっても外字等のコードの割り当ての違いで何種類かありますので日本語処理は結構複雑です。
今回はMac -> UNIXに改行コードを変換するのですが、この場合13だったら10にするという処理だけを行えば良い事になります。
◆メモリに1バイト書き込む
ハンドルを確保してファイルから一気にメモリに読み込む部分は初級編11と全く同じです。今回は変換後に結果をファイルとして書き出すのでファイル保存ダイアログを表示させています。ファイルを2つ以上オープン(開く)場合は、ファイル番号が同じにならないように気を付けてください。また、ファイル番号の上限がFuture Basic 1.0.xとFuture BASIC II(-J)では異なりますので、1.0.xの人はプレファレンスでファイルの上限値を63程度にしておきましょう。今回は2つまでしかファイルをオープンしませんので、特に変更しなくても大丈夫ですが。
さて、メモリから1バイト読み込んでコードが13だったら10に変換する、というプログラムは以下のようになります。
- code% = PEEK([myHandle&] + i&)
- IF code% = _crCode THEN POKE [myHandle&] + i&,_lfCode
最初の行でcode%にメモリから読み出した1バイトが入ります。1バイトなので0〜255までの数値になります。次のIF文で改行コードかどうか調べています。_crCodeおよび_lfCodeは最初に定数として定義してあります。
改行コードだったら、そこのメモリ内容を10に変更します。メモリに1バイト書き込むにはPOKE命令を使います。POKE命令の書式は以下のようになっています。
POKE 書き込み先のアドレス(番地),書き込む値
今回はハンドルを使用していますが、上記プログラムを間違えて
- code% = PEEK(myHandle& + i&)
- IF code% = _crCode THEN POKE myHandle& + i&,_lfCode
とするとシステムエラー等の憂き目にあいます。ポインタの場合は上記の書き方でOKです。
◆一気にファイルに書き込む
ファイルを一気にメモリから書き出すには以下のようにします。
WRITE FILE #2,[myHandle&],fileSize&
このようにすると毎回WRITE #2,A$;1といった書き方よりも数十倍高速に書き込めます。最近のマシンはメモリをふんだんに使えますので、毎回ファイルからデータを読み出して処理するよりも、まずはメモリに読み込んでから処理を行い、最後にファイルに書き出すといった方法が高速でよいでしょう。ちなみに68K Macでは、このような1バイト単位でメモリを処理すると速度が低下します。BASICだから気にならないと思われそうですが、実際に大量に処理をするとかなり速度が違うのが体感できます。
◆終わりに
次回はMac -> Windows(MS-DOS)へ改行コードを変換してみましょう。メモリは読み込みようと書き込み用の2つが必要になります。ファイルで処理した方がプログラム的には楽ですが、メモリの勉強用という事で挑戦してみましょう。
MacからUNIXにコードを変換しましたが、UNIXからMacに改行コードを変換するプログラムを作成してみるとよいでしょう。プログラムをちょっと変更すると動きますので、やってみましょう。
◆今回のプログラムリスト
'
' "改行コードを変換します"
' "CR (13) -> LF (10)"
'
_crCode = 13: '"Macの改行コードはアスキーコードで13"
_lfCode = 10: '"UNIXの改行コードはアスキーコードで13"
LOCAL FN convertCRtoLF
CLS
openfile$ = FILES$(_fOpen,"TEXT",,openRefNum%):' "ファイル選択ダイアログの表示"
savefile$ = FILES$(_fSave,"ファイル名","",saveRefNum%):' "ファイル保存ダイアログの表示"
LONG IF LEN(openfile$)
LONG IF LEN(savefile$)
DEF OPEN "TEXTEdt7"
OPEN "I",#1,openfile$,,openRefNum%: ' "変換元のファイルをオープン"
OPEN "O",#2,savefile$,,saveRefNum%: ' "変換先のファイルをオープン"
fileSize& = LOF(1,1): ' "ファイルサイズを求める"
myHandle& = FN NEWHANDLE(fileSize&): ' "ファイルサイズ分メモリを確保します!"
LONG IF myHandle& = 0: ' "ハンドルサイズが0の時はメモリ不足で確保できなかった!"
PRINT "■ファイルサイズが巨大なため読み込むことが出来ません"
XELSE
PRINT "■変換しています..."
err% = FN HLOCK(myHandle&): ' "メモリが移動しないようにハンドルをロック"
READ FILE #1,[myHandle&],fileSize&: ' "ファイルを読み込む"
FOR i& = 0 TO fileSize&-1: ' "ファイルサイズ分繰り返す"
code% = PEEK([myHandle&] + i&): ' "1バイト読み込む"
IF code% = _crCode THEN POKE [myHandle&] + i&,_lfCode:' "改行コードがCRだったらLFにして書き込む"
NEXT
PRINT "■変換が終了しました"
WRITE FILE #2,[myHandle&],fileSize&: ' "ファイルを書き込む"
err% = FN HUNLOCK(myHandle&): ' "ハンドルロックを解除"
err% = FN DISPOSHANDLE(myHandle&): ' "確保したメモリを解放する"
END IF
CLOSE #1,#2: ' "ファイルを閉じる"
END IF
END IF
END FN
FN convertCRtoLF
PRINT "■■ マウスボタンをクリックすると終了します ■■"
WHILE FN BUTTON = _false:WEND