互換を意識したLineInputを作ってみました。
Input #1, s
などと同様に、Open + Close と共に利用します。
LineInput 1, s
※LineInput (ファイルナンバー), (String型変数)
で使えます。「#1」ではなく「1」と書きます。
もちろん、Input #1, s などと混在しても問題ありません。
コード: 全て選択
'内部関数。
'指定された文字(Byte型)が大文字なら小文字にして返す。
Function __WsByteLower( a As Byte ) As Byte
If( TRUE=IsCharUpper(a) )Then
__WsByteLower = a + 32
Else
__WsByteLower = a
EndIf
EndFunction
'bBaseb文字列の中でSearch文字(Byte型でアスキーコード指定)が最初に現れるポインタを返す。
'無ければNULLを返す。C言語のstrchr()に相当。
' ※上記の__WsByteLower()を利用しています。
Function WsStrChr( pBase As BytePtr, bSearch As Byte ) As BytePtr
dim nBaseSize As Long
dim i As Long
dim j As Long
dim FinishTF As Long
WsStrChr = NULL
nBaseSize = lstrlen( pBase )
i = 0
While( i<nBaseSize-1 )
If( __WsByteLower( GetByte(pBase + i) ) = __WsByteLower( bSearch ) )Then
WsStrChr = pBase + i
ExitWhile
EndIf
i = i + 1
Wend
EndFunction
'LineInputのエミュレート案
Macro LINEINPUT( FileNumber As Long, ByRef strBuffer As String )
Dim poTemp As BytePtr
Dim nReadSize As Long
Dim nFileSize As Long
Dim hFp As Long
Dim nLeftSize As Long
Dim nFpUnitMove As Long
Dim pMark As BytePtr
Dim b As Byte
Dim nShouldGetLength As Long
'パラメータのセット
FileNumber = FileNumber - 1
nFileSize = GetFileSize( _System_hFile[FileNumber], 0 )
hFp = SetFilePointer( _System_hFile[FileNumber], 0, 0, FILE_CURRENT )
nLeftSize = nFileSize - hFp
'一端全て読み込むためのバッファー確保
poTemp = calloc( nLeftSize+1 )
ZeroMemory( poTemp, nLeftSize+1 )
'読み込み
ReadFile( _System_hFile[FileNumber], _
poTemp, _
nLeftSize, _
VarPtr(nReadSize), _
ByVal NULL )
'LFで分割。
pMark = WsStrChr( poTemp, 10 )
If( pMark=NULL )Then
nShouldGetLength = lstrlen( poTemp )
strBuffer = ZeroString( nShouldGetLength + 1 )
strBuffer = lstrcpy( strBuffer, poTemp )
Exit Macro
Else
'引数に代入すべき文字列の長さを得る。
b = GetByte( pMark-1 )
If( b=13 )Then
nShouldGetLength = pMark - poTemp - 1
Else
nShouldGetLength = pMark - poTemp
EndIf
'ファイルポインタの移動先(代入文字列の分だけ進める)を計算。
nFpUnitMove = hFp + ( pMark - poTemp ) + 1
EndIf
'LFの手前までを引数に代入
SetByte( poTemp + nShouldGetLength, 0 )
strBuffer = ZeroString( nShouldGetLength + 1 )
strBuffer = lstrcpy( strBuffer, poTemp )
'ファイルポインタの調整
hFp = SetFilePointer( _System_hFile[FileNumber], nFpUnitMove, 0, FILE_BEGIN )
'バッファー開放
free( poTemp )
End Macro
Ver3.13 + Win2000 で動作確認。
わざわざWsStrChr()とか定義しているのは、私の好みのせいです(^^;)
行の終端は LF or CR+LF で判断しています。
問題は、
LineInput #1, s
でなく
LineInput 1, s
と#を外して書かなきゃいけないため、Ver2.xのABファイルをそのまま移せないこと。
Inputの定義ファイルを見ると
Macro INPUT_FromFile(FileNumber As Long)
で#が使えているのですが・・・Macroの仕様はよく分かりません。
BackSearchABで「NoWestさんのページに以前書いてあった話で
Macroに関するものが」との記述を見つけましたが、辿れず。
もう消えているのか、見つけられなかっただけか。
ご存知の方いますか?
>> Line Input については,一応代替処理用ライブラリがあるのですが
>> AB2のLine Inputよりも遅くなってしまうようです。
>>
http://www50.tok2.com/home/losedog2/download.htm#ABLIB (まけイヌさん作)
まけイヌさんのライブラリは私も以前に使わせてもらいましたが、
ある条件下で、同じ文を二度読み込んで来たり、ファイルの最後まで読み込んでしまったり、
というバグが合ったように思います。
・・・と、言うだけ言っておいて『発生条件不明』なので大変恐縮ですが。
やー、その後String型の文字数上限などの問題から、
BytePtr型+ReadFileで一括読み込みするようになったもので、
エラーの原因究明を放置しちゃってるんですよ。
今となっては、そのエラーが出たファイル自体、何処に行ったか分かりません・・・。
もうバグ修正版がアップされていましたら、ごめんなさい。
>> 私も現在試しに,もっと速い方法がないか作ってみてるところですけどね。
他のスレでも「Ver2.xに比べて遅い」との記述を見かけた気がしますが、
方法次第でもっと速度が上がるものなのですか?
それは考えもしませんでした。
バッファーに読み込んで1Byteずつ順に走査してLFを探していく方法しか、
思いつきませんでした。
上のコードでは、将来的に最初にファイル終端まで読み込んでおいて、
LineInputが呼び出されたら、その読み込んでおいたバッファーから値を
返せば早くなるかな~と、考えて組んでますが、そうすると
Open + Close 文の定義も書き換える必要が出てくるので、
今回はそこまではやっていません。