プログラム講座 初級編11
- テキストファイルの行数を数える -
初級編11です。今回は初級編9、10で解説したメモリの使用方法の1つを解説します。初級編という事で簡単な「ファイルの行数を調べる」という処理を行います。
◆行数を数える方法
行数を数えるには「改行コード」だったら行数を増やすだけです。特にメモリを確保して処理をしなくてもファイルから1文字ずつ読み込んで調べる方法もあります。テキストが100KB程度であれば全然問題ありませんが、500KB、1MBサイズとなるとファイルから1文字づつ読み込んでいたのでは時間がかかってしまいます。
メモリを確保しファイル内容を一気に読み込みメモリに読み込まれた内容を1バイト毎に調べれば速度は劇的に速くなります。ファイルから1文字づつ読み込むプログラムは勉強用に自作してみると良いでしょう。
◆ファイルサイズを求めるには?
メモリに読み込むために、あらかじめファイルサイズを求めておかなければなりません。ファイルサイズを求めるには
ファイルサイズ = LOF(ファイル番号,1)
といったようになります。ファイル番号はOPEN "O",#2〜の#2の番号(つまり2)です。ファイルサイズは「ロング変数」(変数の最後に&を付加)でなければなりません。
ファイルサイズが求まったらFN NEWHANDLEを使ってメモリを確保します。
ハンドルが0かどうかをチェックし0でなければハンドルをロックします。
◆一気にファイルを読み込む
ファイルを一気にメモリに読み込むには以下のようにします。
READ FILE #1,[myHandle&],fileSize&
[myHandle&]はPEEK LONG(myHandle&)と同じ意味です。こうすれば数百KB程度であれば瞬時に読み込めます。
後は読み込んだファイルサイズ分だけバイト単位で読み込み改行コードかどうか調べていきます。1バイト読み込むには
code% = PEEK([myHandle&] + i&)
とします。
短いプログラムなので順を追ってみていけばわかると思います。
◆終わりに
次回は「改行コード変換」プログラムを作成してみます。改行コード変換プログラムは簡単ですが、メモリの勉強としてメモリに読み込み、メモリに書き込み後ファイルに出力するといった処理を行います。
◆今回のプログラムリスト
'
' "テキストファイルの行数を数えます"
'
_crCode = 13: '"改行コードはアスキーコードで13"
LOCAL FN lineCounter
CLS
openfile$ = FILES$(_fOpen,"TEXT",,openRefNum%):' "ファイル選択ダイアログの表示"
LONG IF LEN(openfile$)
OPEN "I",#1,openfile$,,openRefNum%: ' "分割元のファイルをオープン"
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&: ' "ファイルを読み込む"
lineCount& = 1: ' "行数を1に設定する"
FOR i& = 0 TO fileSize&-1: ' "ファイルサイズ分繰り返す"
code% = PEEK([myHandle&] + i&): ' "1バイト読み込む"
IF code% = _crCode THEN lineCount& = lineCount& + 1:' "改行コードだったら行数に1を足す"
NEXT
PRINT "■";lineCount&;"行ありました"
err% = FN HUNLOCK(myHandle&): ' "ハンドルロックを解除"
err% = FN DISPOSHANDLE(myHandle&): ' "確保したメモリを解放する"
END IF
CLOSE #1: ' "ファイルを閉じる"
END IF
END FN
FN lineCounter
PRINT "■■ マウスボタンをクリックすると終了します ■■"
WHILE FN BUTTON = _false:WEND