Distinguidos
Se puede contar un carΓ‘cter especifico de un archivo de texto, Ej. contar cuantos Chr(12) saltos de pΓ‘gina existen, sin necesidad de recorrer lΓnea a lΓnea todo el archivo.
Gracias por la ayuda.
Saludos,
Adhemar
Adhemar C.
Distinguidos
Se puede contar un carΓ‘cter especifico de un archivo de texto, Ej. contar cuantos Chr(12) saltos de pΓ‘gina existen, sin necesidad de recorrer lΓnea a lΓnea todo el archivo.
Gracias por la ayuda.
Saludos,
Adhemar
v_busca="CHR12"
v_handle=fopen("arquivo.txt")
v_tamanho=fseek(v_handle,0,2) // pega tamanho do arquivo
fseek(v_handle,0,0)
v_lbusca=len(v_busca)
do while .t.
Β Β v_buffer=space(v_lbusca)
Β Β v_lidos=fread(v_handle,@v_buffer,v_lbusca)
Β Β if v_lidos < v_lbusca
Β Β Β Β exit
Β Β endif
Β Β if v_buffer = v_busca
Β Β Β Β v_pos=fseek(v_handle,0,1)
Β Β Β Β exit
Β Β endif
enddo
? "a posiΓ§Γ£o da string no arquivo Γ© em"
? v_pos
fclose(v_handle) oFile:= TTxtFile():New( cFile )
Do while !oFile:EOF()
cLinea :=oFile:ReadLine()
IF At(Chr(12),cLinea)>0
If !oFile:EOF()
nPagTot++
Endi
Endi
oFile:Skip()
EndDo
oFile:End()Adhemar,
Puedes usar la function StrCharCount( cString, cChar ) --> nTimes de FWH estΓ‘ implementada en C y es muy rapida ![]()
Ojo que cChar ha de ser de tipo cadena, ej: Chr( 12 )
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: BrowText() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 12, 1994 β
Β¦β β
Β¦β Notes.........: Browsing of a text file. β
Β¦β β
Β¦β β
Β¦β Parameters....: nTop NUMERIC β
Β¦β Top Row Position on Screen β
Β¦β nLeft NUMERIC β
Β¦β Left Column Position on Screen β
Β¦β nBottom NUMERIC β
Β¦β Bottom Row Position on Screen β
Β¦β nRight NUMERIC β
Β¦β Right Column Position on Screen β
Β¦β cFileName CHARACTER β
Β¦β Name of file to browse β
Β¦β [lFrame] LOGICAL β
Β¦β Display a frame around the browse window β
Β¦β β
Β¦β Returns.......: NIL β
Β¦β β
Β¦β Functions.....: FileInit(), Skipper(), GetLast(), β
Β¦β GetFirst(), GoPrevLn(), GoNextLn(), β
Β¦β FReadLn(), TBrowse(), StdMeth() β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
#include "inkey.ch"
#xtranslate FALSE => .F.
#xtranslate TRUE => .T.
#xtranslate CR => Chr(13)
#xtranslate LF => Chr(10)
#xtranslate CRLF => CR + LF
#command DEFAULT <variable1> TO <value1> [, <variableN> TO <valueN> ] => ;
IF <variable1> == NIL; <variable1> := <value1>; END;
[; IF <variableN> == NIL; <variableN> := <valueN>; END ]
STATIC cLine, ; // Current Line
nFileSize // File Size
#include "fileio.ch"
#define FTELL(nHandle) FSEEK(nHandle, 0, FS_RELATIVE)
#define MAX_LINE_LEN 256
FUNCTION BrowText( nTop, nLeft, nBottom, nRight, cFileName, lFrame )
LOCAL oBrowse, ; // Browse Object
oCol, ; // Browse Column Object
nHandle // File Handle
DEFAULT nTop TO 0, nLeft TO 0, nBottom TO MAXROW(), nRight TO MAXCOL(), ;
lFrame TO TRUE
// Open the file
nHandle := FileInit(cFileName)
IF nHandle == 0
RETURN NIL
ENDIF
// Display the frame adjust the coordinates for the browse object
IF lFrame
DISPBOX(nTop, nLeft, nBottom, nRight)
nTop++
nLeft++
nBottom--
nRight--
ENDIF
// Create the browse object
oBrowse := TBROWSENEW(nTop, nLeft, nBottom, nRight)
// Create the first column object
oCol := TBCOLUMNNEW(, {|| cLine })
oCol:width := (nRight - nLeft) + 1
oBrowse:addColumn(oCol)
// Create the second column object
oCol := TBCOLUMNNEW(, {|| SUBSTR(cLine, (nRight - nLeft) + 2) })
oCol:width := (nRight - nLeft) + 1
oBrowse:addColumn(oCol)
// Browse movement blocks
oBrowse:goBottomBlock := {|| GetLast(nHandle) }
oBrowse:goTopBlock := {|| GetFirst(nHandle) }
oBrowse:skipBlock := {|n| Skipper(n, nHandle) }
// Activate it...
TBrowse(oBrowse)
// Close the file
FCLOSE(nHandle)
RETURN NIL
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: Skipper() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Attempts to skip a specified number of rows in the β
Β¦β browse window. β
Β¦β β
Β¦β β
Β¦β Parameters....: nSkip NUMERIC β
Β¦β Number of rows to skip β
Β¦β nHandle NUMERIC β
Β¦β File Handle β
Β¦β β
Β¦β β
Β¦β Returns.......: Number of rows successfully skipped β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION Skipper( nSkip, nHandle )
LOCAL nSkipped := 0
// Skip down
IF nSkip > 0
DO WHILE nSkipped != nSkip .AND. GoNextLn( nHandle )
nSkipped++
ENDDO
// Skip Up
ELSE
DO WHILE nSkipped != nSkip .AND. GoPrevLn( nHandle )
nSkipped--
ENDDO
ENDIF
RETURN (nSkipped)
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: FileInit β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 12, 1994 β
Β¦β β
Β¦β Notes.........: Initialize the file to browse β
Β¦β β
Β¦β β
Β¦β Parameters....: nFname CHARACTER β
Β¦β Name of file to initialize β
Β¦β β
Β¦β β
Β¦β Returns.......: File Handle β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION FileInit( nFname )
LOCAL nHandle // File Handle
IF (nHandle := FOPEN(nFname)) > 0
FSEEK(nHandle, 0, FS_END)
nFileSize := FTELL(nHandle)
GetFirst(nHandle)
ENDIF
RETURN (nHandle)
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: GetLast() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Moves to the last line of the file β
Β¦β β
Β¦β β
Β¦β Parameters....: nHandle NUMERIC β
Β¦β File Handle β
Β¦β β
Β¦β Returns.......: NIL β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION GetLast( nHandle )
FSEEK(nHandle, -1, FS_END)
GoPrevLn( nHandle )
RETURN NIL
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: GetFirst() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Moves the file pointer to the first line of the file. β
Β¦β β
Β¦β β
Β¦β Parameters....: nHandle NUMERIC β
Β¦β File Handle β
Β¦β β
Β¦β β
Β¦β Returns.......: NIL β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION GetFirst( nHandle )
FSEEK(nHandle, 0, FS_SET)
FReadLn(nHandle, @cline)
FSEEK(nHandle, 0, FS_SET)
RETURN NIL
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: GoPrevLn β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Move the file pointer to the previous line of the file.β
Β¦β β
Β¦β β
Β¦β Parameters....: nHandle NUMERIC β
Β¦β File Handle β
Β¦β β
Β¦β β
Β¦β Returns.......: TRUE if move was successful, or FALSE otherwise. β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION GoPrevLn( nHandle )
LOCAL nOrigPos, ; // Original File Pointer Position
nMaxRead, ; // Maximum Line Length
nNewPos, ; // New File Pointer Position
lMoved, ; // Pointer Moved
cBuff, ; // Line buffer
nWhereCrLf, ; // Position of CRLF
nPrev // Previous File Pointer Position
// Save Original file position
nOrigPos := FTELL(nHandle)
IF nOrigPos = 0
lMoved := FALSE
ELSE
lMoved := TRUE
IF nOrigPos != nFileSize
// Skip over preceeding CR / LF
FSEEK(nHandle, -2, FS_RELATIVE)
ENDIF
nMaxRead := MIN(MAX_LINE_LEN, FTELL(nHandle))
// Capture the line into a buffer, strip off the CRLF
cBuff := SPACE(nMaxRead)
nNewPos := FSEEK(nHandle, -nMaxRead, FS_RELATIVE)
FREAD(nHandle, @cBuff, nMaxRead)
nWhereCrLf := RAT(CRLF, cBuff)
IF nWhereCrLf = 0
nPrev := nNewPos
cLine = cBuff
ELSE
nPrev := nNewPos + nWhereCrLf + 1
cline := SUBSTR(cBuff, nWhereCrLf + 2)
ENDIF
// Move to the beginning of the line
FSEEK(nHandle, nPrev, FS_SET)
ENDIF
RETURN (lMoved)
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: GoNext β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Try to move the File Pointer to the next line of the β
Β¦β file. β
Β¦β β
Β¦β β
Β¦β Parameters....: nHandle NUMERIC β
Β¦β File Handle β
Β¦β β
Β¦β β
Β¦β Returns.......: TRUE if move was successful, or FALSE otherwise. β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION GoNextLn( nHandle )
LOCAL nSavePos, ; // Save File pointer position
cBuff := "", ; // Line Buffer
lMoved, ; // Pointer Moved
nNewPos // New File Pointer Position
// Save the file pointer position
nSavePos := FTELL(nHandle)
// Find the end of the current line
FSEEK(nHandle, LEN(cLine) + 2, FS_RELATIVE)
nNewPos := FTELL(nHandle)
// Read in the next line
IF FReadLn(nHandle, @cBuff)
lMoved := TRUE
cLine := cBuff
FSEEK(nHandle, nNewPos, FS_SET)
ELSE
lMoved := FALSE
FSEEK(nHandle, nSavePos, FS_SET)
ENDIF
RETURN (lMoved)
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: FReadLn() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Reads the current line of the file into a buffer β
Β¦β β
Β¦β β
Β¦β β
Β¦β Parameters....: nHandle NUMERIC β
Β¦β File Handle Number β
Β¦β cBuffer CHARACTER β
Β¦β Line Buffer β
Β¦β β
Β¦β Returns.......: TRUE if anything was read in. β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION FReadLn( nHandle, cBuffer )
LOCAL nEOL, ; // End Of Line Postion
nRead, ; // Number of characters read
nSaveFPos // Saved File Postion
cBuffer = SPACE(MAX_LINE_LEN)
// First save current file pointer
nSaveFPos = FTELL(nHandle)
nRead = FREAD(nHandle, @cBuffer, MAX_LINE_LEN)
IF (nEOL := AT(CRLF, SUBSTR(cBuffer, 1, nRead))) = 0
// Line overflow or eof
// Cline has the line we need
ELSE
// Copy up to EOL
cBuffer = SUBSTR(cBuffer, 1, nEOL - 1)
// Position file pointer to next line
FSEEK(nHandle, nSaveFPos + nEOL + 1, FS_SET)
ENDIF
RETURN (nRead != 0)
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: TBrowse() β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Pass tbrowse() a tbrowse object, and up to three code β
Β¦β blocks. The first is the code block to check for keys β
Β¦β before checking the standard keys, the second β
Β¦β indicates how long the user stays in the browse, the β
Β¦β third code block to check keys after the standard β
Β¦β keys have been checked. β
Β¦β β
Β¦β Parameters....: oBrowse OBJECT β
Β¦β TBrowse Object β
Β¦β [bBefore] BLOCK β
Β¦β Block to handle before keys β
Β¦β [bWhileCond] BLOCK β
Β¦β Block to exit of browse β
Β¦β [bAfter] BLOCK β
Β¦β Block to handle after keys β
Β¦β β
Β¦β Returns.......: NIL β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION TBrowse( oBrowse, bBefore, bWhileCond, bAfter )
LOCAL nKey, ; // ASCII Key Pressed
lExitRequested // Exit Requested
DEFAULT bBefore TO {|nKey| IF(nKey == K_ENTER .OR. nKey == K_ESC, ;
lExitRequested := TRUE, FALSE) }
DEFAULT bWhileCond TO {|| !lExitRequested}
DEFAULT bAfter TO {|| FALSE}
lExitRequested := FALSE
DO WHILE EVAL(bWhileCond, oBrowse)
DO WHILE NEXTKEY() = 0 .AND. !oBrowse:stabilize()
ENDDO
nKey = INKEY(0)
IF EVAL(bBefore, nKey, oBrowse)
// Processed key as before key
ELSEIF StdMeth(nKey, oBrowse)
// Processed key as standard key
ELSEIF oBrowse:stable .AND. EVAL(bAfter, nKey, oBrowse)
// Processed key as after key
ENDIF
ENDDO
RETURN NIL
/*
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β Function......: StdMeth β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Β¦β ORIGINAL β
Β¦β Programmer....: Rick Spence β
Β¦β Date..........: NA β
Β¦β β
Β¦β LAST MODIFICATION β
Β¦β Author........: Mark Nowakowski β
Β¦β Date..........: May 10, 1994 β
Β¦β β
Β¦β Notes.........: Process standard keys of browse β
Β¦β β
Β¦β β
Β¦β β
Β¦β Parameters....: nKey NUMERIC β
Β¦β ASCII Code of key pressed β
Β¦β oBrowse OBJECT β
Β¦β Tbrowse Object β
Β¦β β
Β¦β Returns.......: TRUE if key handled correctly. β
Β¦β β
Β¦ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
*/
STATIC FUNCTION StdMeth( nKey, oBrowse )
LOCAL lKeyHandled := TRUE // Key Processed
DO CASE
CASE nKey = K_DOWN
oBrowse:down()
CASE nKey = K_UP
oBrowse:up()
CASE nKey = K_PGDN
oBrowse:pageDown()
CASE nKey = K_PGUP
oBrowse:pageUp()
CASE nKey = K_CTRL_PGUP
oBrowse:goTop()
CASE nKey = K_CTRL_PGDN
oBrowse:goBottom()
CASE nKey = K_RIGHT
oBrowse:right()
CASE nKey = K_LEFT
oBrowse:left()
CASE nKey = K_HOME
oBrowse:home()
CASE nKey = K_END
oBrowse:end()
CASE nKey = K_CTRL_LEFT
oBrowse:panLeft()
CASE nKey = K_CTRL_RIGHT
oBrowse:panRight()
CASE nKey = K_CTRL_HOME
oBrowse:panHome()
CASE nKey = K_CTRL_END
oBrowse:panEnd()
OTHERWISE
lKeyHandled := FALSE
ENDCASE
RETURN (lKeyHandled) DEFINE DIALOG oDlgView FROM nDWTop, nDWLeft TO nDWBottom, nDWRight PIXEL TITLE "Vista Preliminar de: "+cNomLST;oDlgView:lHelpIcon:=.F.
oBrw1:= TXBrowse():New( oDlgView )
WITH OBJECT oBrw1
:nMarqueeStyle := MARQSTYLE_HIGHLWIN7
:lMultiSelect := .f.
:lRecordSelector:=.F.
:nFreeze:=1
:nColSel:=2
:nHeaderHeight:=7
:SetArray( aTexto,.T. )
END
oBrw1:aCols[1]:oDataFont:= { || iif( lFont,oFont,oBig) }
oBrw1:bChange:={|| (VerPag())}
AEval( oBrw1:aCols, { | oCol | oCol:bPaintText := { | oCol, hDC, cData, aRect | PaintColx( oCol, hDC, cData, aRect ) } } )
oBrw1:CreateFromCode()
oBrw1:bKeyDown:={|nKey| iif( nKey=VK_F3, BuscaCad(vQue,oBrw1),Nil )}
ACTIVATE DIALOG oDlgView ON INIT (BtnPre(oDlgView,cFile),VerPag(),oBrw1:Move(31,0,( oDlgView:nRight-oDlgView:nLeft)-26,(oDlgView:nBottom-oDlgView:nTop)-70) )Adhemar,
Un array de 159.143 elementos es un gran array y es logico que le cueste. Que mide el fichero completo ?
Sin embargo con la tecnica de Rick Spence, no hay que crear ningun array ni sobrecargar la memoria. Solo se leen desde el fichero en el disco las lineas que se estan mostrando. Ya veras que diferencia de velocidad
Antonio, en fichero mide 19708 KB
Me parece interesante el ejemplo, lo estoy analizando
Gracias.
Saludos,
Adhemar
#include "FiveWin.ch"
#include "xbrowse.ch"
#include "fileio.ch"
#define FTELL(nHandle) Β FSEEK(nHandle, 0, FS_RELATIVE)
#define MAX_LINE_LEN 256
static hFile, cLine, nFileSize
function Main()
Β Β local oWnd, oBrw, nBofPos, nEofPos, nLines
Β Β
Β Β nLines = StrCharCount( MemoRead( "brwtext.prg" ), Chr( 13 ) )
Β Β
Β Β hFile = FOpen( "brwtext.prg" )
Β Β FSeek( hFile, 0, FS_END )
Β Β Β nFileSize = FTELL( hFile )
Β Β GoBottomLine( hFile )
Β Β nEofPos = nFileSize - Len( cLine )
Β Β GoTopLine( hFile )
Β Β nBofPos = Len( cLine )
Β Β cLine = PadR( cLine, 80 )
Β Β DEFINE WINDOW oWnd
Β Β @ 0, 0 XBROWSE oBrw cLine OF oWnd
Β Β Β
Β Β oBrw:CreateFromCode()
Β Β oBrw:bKeyCount = { || nLines }
Β Β oBrw:bGoTop Β Β = { || GoTopLine() }
Β Β oBrw:bGoBottom = { || GoBottomLine() }
Β Β oBrw:bSkip Β Β = { | nSkip | Skipper( IfNil( nSkip, 1 ), hFile ) }
Β Β oBrw:bBof Β Β Β = { || FTELL( hFile ) < nBofPos }
Β Β oBrw:bEof Β Β Β = { || FTELL( hFile ) > nEofPos }
Β Β oWnd:oClient = oBrw
Β Β oBrw:Refresh()
Β Β
Β Β ACTIVATE WINDOW oWnd
Β Β
Β Β FClose( hFile )
return nil
function GoTopLine( hFile )
Β Β FSeek( hFile, 0, FS_SET )
Β Β FReadLn( hFile, @cLine )
Β Β FSeek( hFile, 0, FS_SET )
return nil
function GoBottomLine( hFile )
Β Β FSeek( hFile, -1, FS_END )
Β Β GoPrevLn( hFile )
return nil
STATIC FUNCTION FReadLn( nHandle, cBuffer )
LOCAL nEOL, Β Β ;Β Β // End Of Line Postion
Β Β Β Β nRead, Β ;Β Β // Number of characters read
Β Β Β Β nSaveFPosΒ Β // Saved File Postion
cBuffer = SPACE(MAX_LINE_LEN)
// First save current file pointer
nSaveFPos = FTELL(nHandle)
nRead = FREAD(nHandle, @cBuffer, MAX_LINE_LEN)
IF (nEOL := AT(CRLF, SUBSTR(cBuffer, 1, nRead))) = 0
Β Β // Line overflow or eof
Β Β // Cline has the line we need
ELSE
Β Β // Copy up to EOL
Β Β cBuffer = SUBSTR(cBuffer, 1, nEOL - 1)
Β Β // Position file pointer to next line
Β Β FSEEK(nHandle, nSaveFPos + nEOL + 1, FS_SET)
ENDIF
RETURN (nRead != 0)
STATIC FUNCTION Skipper( nSkip, nHandle )
LOCAL nSkipped := 0
// Skip down
IF nSkip > 0
Β Β DO WHILE nSkipped != nSkip .AND. GoNextLn( nHandle )
Β Β Β Β nSkipped++
Β Β ENDDO
// Skip Up
ELSE
Β Β DO WHILE nSkipped != nSkip .AND. GoPrevLn( nHandle )
Β Β Β Β nSkipped--
Β Β ENDDO
ENDIF
RETURN (nSkipped)
STATIC FUNCTION GoNextLn( nHandle )
LOCAL nSavePos,Β Β Β ;Β Β // Save File pointer position
Β Β Β cBuff := "", Β ;Β Β // Line Buffer
Β Β Β lMoved, Β Β Β Β Β ;Β Β // Pointer Moved
Β Β Β nNewPosΒ Β Β Β Β Β Β Β // New File Pointer Position
// Save the file pointer position
nSavePos := FTELL(nHandle)
// Find the end of the current line
FSEEK(nHandle, LEN(cLine) + 2, FS_RELATIVE)
nNewPos := FTELL(nHandle)
// Read in the next line
IF FReadLn(nHandle, @cBuff)
Β Β lMoved := .T.
Β Β cLine := cBuff
Β Β FSEEK(nHandle, nNewPos, FS_SET)
ELSE
Β Β lMoved := .F.
Β Β FSEEK(nHandle, nSavePos, FS_SET)
ENDIF
RETURN (lMoved)
STATIC FUNCTION GoPrevLn( nHandle )
LOCAL nOrigPos,Β ;Β Β // Original File Pointer Position
Β Β Β Β nMaxRead, Β ;Β Β // Maximum Line Length
Β Β Β Β nNewPos, Β Β ;Β Β // New File Pointer Position
Β Β Β lMoved, Β Β Β ;Β Β // Pointer Moved
Β Β Β cBuff, Β Β Β Β ;Β Β // Line buffer
Β Β Β nWhereCrLf, ;Β // Position of CRLF
Β Β Β nPrevΒ Β Β Β Β Β Β // Previous File Pointer Position
// Save Original file position
nOrigPos := FTELL(nHandle)
IF nOrigPos = 0
Β Β lMoved := .F.
ELSE
Β Β lMoved := .T.
Β Β IF nOrigPos != nFileSize
Β Β Β Β // Β Skip over preceeding CR / LF
Β Β Β Β FSEEK(nHandle, -2, FS_RELATIVE)
Β Β ENDIF
Β Β nMaxRead := MIN(MAX_LINE_LEN, FTELL(nHandle))
Β Β // Capture the line into a buffer, strip off the CRLF
Β Β cBuff := SPACE(nMaxRead)
Β Β nNewPos := FSEEK(nHandle, -nMaxRead, FS_RELATIVE)
Β Β FREAD(nHandle, @cBuff, nMaxRead)
Β Β nWhereCrLf := RAT(CRLF, cBuff)
Β Β IF nWhereCrLf = 0
Β Β Β Β nPrev := nNewPos
Β Β Β Β cLine = cBuff
Β Β ELSE
Β Β Β Β nPrev := nNewPos + nWhereCrLf + 1
Β Β Β Β cline := SUBSTR(cBuff, nWhereCrLf + 2)
Β Β ENDIF
Β Β // Move to the beginning of the line
Β Β FSEEK(nHandle, nPrev, FS_SET)
ENDIF
RETURN (lMoved)#include "FiveWin.ch"
#include "xbrowse.ch"
#include "fileio.ch"
#define FTELL(nHandle) FSEEK(nHandle, 0, FS_RELATIVE)
#define MAX_LINE_LEN 256
static hFile, cLine, nFileSize
function Main()
local oWnd, oBrw, nBofPos, nEofPos, nLines
nLines = StrCharCount( MemoRead( "brwtext.prg" ), Chr( 13 ) )
hFile = FOpen( "brwtext.prg" )
FSeek( hFile, 0, FS_END )
nFileSize = FTELL( hFile )
GoBottomLine( hFile )
nEofPos = nFileSize - Len( cLine )
GoTopLine( hFile )
nBofPos = Len( cLine )
cLine = PadR( cLine, 80 )
DEFINE WINDOW oWnd
@ 0, 0 XBROWSE oBrw cLine OF oWnd
oBrw:CreateFromCode()
oBrw:bKeyCount = { || nLines }
oBrw:bGoTop = { || GoTopLine() }
oBrw:bGoBottom = { || GoBottomLine() }
oBrw:bSkip = { | nSkip | Skipper( IfNil( nSkip, 1 ), hFile ) }
oBrw:bBof = { || FTELL( hFile ) < nBofPos }
oBrw:bEof = { || FTELL( hFile ) > nEofPos }
oWnd:oClient = oBrw
GoTopLine( hFile )
ACTIVATE WINDOW oWnd
FClose( hFile )
return nil
function GoTopLine( hFile )
FSeek( hFile, 0, FS_SET )
FReadLn( hFile, @cLine )
FSeek( hFile, 0, FS_SET )
return nil
function GoBottomLine( hFile )
FSeek( hFile, -1, FS_END )
GoPrevLn( hFile )
return nil
STATIC FUNCTION FReadLn( nHandle, cBuffer )
LOCAL nEOL, ; // End Of Line Postion
nRead, ; // Number of characters read
nSaveFPos // Saved File Postion
cBuffer = SPACE(MAX_LINE_LEN)
// First save current file pointer
nSaveFPos = FTELL(nHandle)
nRead = FREAD(nHandle, @cBuffer, MAX_LINE_LEN)
IF (nEOL := AT(CRLF, SUBSTR(cBuffer, 1, nRead))) = 0
// Line overflow or eof
// Cline has the line we need
ELSE
// Copy up to EOL
cBuffer = SUBSTR(cBuffer, 1, nEOL - 1)
// Position file pointer to next line
FSEEK(nHandle, nSaveFPos + nEOL + 1, FS_SET)
ENDIF
RETURN (nRead != 0)
STATIC FUNCTION Skipper( nSkip, nHandle )
LOCAL nSkipped := 0
// Skip down
IF nSkip > 0
DO WHILE nSkipped != nSkip .AND. GoNextLn( nHandle )
nSkipped++
ENDDO
// Skip Up
ELSE
DO WHILE nSkipped != nSkip .AND. GoPrevLn( nHandle )
nSkipped--
ENDDO
ENDIF
RETURN (nSkipped)
STATIC FUNCTION GoNextLn( nHandle )
LOCAL nSavePos, ; // Save File pointer position
cBuff := "", ; // Line Buffer
lMoved, ; // Pointer Moved
nNewPos // New File Pointer Position
// Save the file pointer position
nSavePos := FTELL(nHandle)
// Find the end of the current line
FSEEK(nHandle, LEN(cLine) + 2, FS_RELATIVE)
nNewPos := FTELL(nHandle)
// Read in the next line
IF FReadLn(nHandle, @cBuff)
lMoved := .T.
cLine := cBuff
FSEEK(nHandle, nNewPos, FS_SET)
ELSE
lMoved := .F.
FSEEK(nHandle, nSavePos, FS_SET)
ENDIF
RETURN (lMoved)
STATIC FUNCTION GoPrevLn( nHandle )
LOCAL nOrigPos, ; // Original File Pointer Position
nMaxRead, ; // Maximum Line Length
nNewPos, ; // New File Pointer Position
lMoved, ; // Pointer Moved
cBuff, ; // Line buffer
nWhereCrLf, ; // Position of CRLF
nPrev // Previous File Pointer Position
// Save Original file position
nOrigPos := FTELL(nHandle)
IF nOrigPos = 0
lMoved := .F.
ELSE
lMoved := .T.
IF nOrigPos != nFileSize
// Skip over preceeding CR / LF
FSEEK(nHandle, -2, FS_RELATIVE)
ENDIF
nMaxRead := MIN(MAX_LINE_LEN, FTELL(nHandle))
// Capture the line into a buffer, strip off the CRLF
cBuff := SPACE(nMaxRead)
nNewPos := FSEEK(nHandle, -nMaxRead, FS_RELATIVE)
FREAD(nHandle, @cBuff, nMaxRead)
nWhereCrLf := RAT(CRLF, cBuff)
IF nWhereCrLf = 0
nPrev := nNewPos
cLine = cBuff
ELSE
nPrev := nNewPos + nWhereCrLf + 1
cline := SUBSTR(cBuff, nWhereCrLf + 2)
ENDIF
// Move to the beginning of the line
FSEEK(nHandle, nPrev, FS_SET)
ENDIF
RETURN (lMoved)#include "FiveWin.ch"
#include "xbrowse.ch"
function Main()
Β Β local oWnd, oBrw
Β Β DEFINE WINDOW oWnd
Β Β @ 0,0 XBROWSE oBrw OF oWnd DATASOURCE ;
Β Β Β TTxtFile():New( "c:\fwh\samples\fivedbu.prg", 0 ) ;
Β Β Β COLUMNS "cLine"
Β Β oBrw:nStretchCol := 1
Β Β oBrw:CreateFromCode()
Β Β oWnd:oClient := oBrw
Β Β ACTIVATE WINDOW oWnd MAXIMIZED
return nil#include "FiveWin.ch"
#include "xbrowse.ch"
#include "fileio.ch"
#define FTELL(nHandle) FSEEK(nHandle, 0, FS_RELATIVE)
#define MAX_LINE_LEN 255
static hFile
static nFileSize, nLines
static nLineNo := 1, nLineAt := 0, cLine := ""
static nLastAt := 0
static cBuf
//----------------------------------------------------------------------------//
function Main()
local oWnd, oBrw
cBuf := Space( MAX_LINE_LEN )
hFile := FOpen( "brwtext2.prg" )
nFileSize := FSeek( hFile, 0, FS_END )
nLines := CountCRLF() + 1
GoTopLine()
DEFINE WINDOW oWnd
@ 0,0 XBROWSE oBrw OF oWnd FIELDS nLineNo, cLine ;
HEADERS "No", "Text" PICTURES "9999" FOOTERS
WITH OBJECT oBrw
:nDataType := DATATYPE_USER
//
:bBof := ;
:bEof := { || nFileSize == 0 }
:bGoTop := { || GoTopLine() }
:bGoBottom := { || GoBottomLine() }
:bKeyCount := { || nLines }
:bKeyNo := ;
:bBookMark := { |n| If( n == nil, nLineNo, GoToLine( n ) ) }
:bSkip := { |n| SkipLines( n ) }
//
:aCols[ 1 ]:bFooter := { || oBrw:nLen }
:nStretchCol := 2
:lVThumbTrack := .t.
:nMarqueeStyle := MARQSTYLE_HIGHLWIN7
//
:CreateFromCode()
END
oWnd:oClient := oBrw
ACTIVATE WINDOW oWnd
FClose( hFile )
return 0
//----------------------------------------------------------------------------//
static function GoTopLine()
FSeek( hFile, 0, FS_SET )
cLine := ReadLine()
nLineNo := 1
nLineAt := 0
return nil
//----------------------------------------------------------------------------//
static function GoBottomLine()
FSeek( hFile, nLastAt, FS_SET )
cLine := ReadLine()
nLineNo := nLines
nLineAt := nLastAt
return nil
//----------------------------------------------------------------------------//
static function ReadLine()
local nRead, nAt
nRead := FRead( hFile, @cBuf, MAX_LINE_LEN )
cLine := Left( cBuf, nRead )
if ( nAt := At( CRLF, cLine ) ) > 0
cLine := Left( cLine, nAt - 1 )
endif
return cLine
//----------------------------------------------------------------------------//
static function GoNextLine()
if nLineAt >= nLastAt
return .f.
endif
nLineAt += ( Len( cLine ) + 2 )
nLineNo++
FSeek( hFile, nLineAt, FS_SET )
ReadLine()
return .t.
//----------------------------------------------------------------------------//
static function GoPrevLine()
local nStart, nToRead, nRead, nAt, c
if nLineAt < 2
return .f.
endif
nToRead := Min( MAX_LINE_LEN, nLineAt - 2 )
nStart := nLineAt - 2 - nToRead
FSeek( hFile, nStart, FS_SET )
nRead := FRead( hFile, @cBuf, nToRead )
c := Left( cBuf, nRead )
if ( nAt := RAt( CRLF, c ) ) > 0
cLine := SubStr( c, nAt + 2 )
nLineAt := nStart + nAt + 1
else
cLine := c
nLineAt := nStart
endif
nLineNo--
return .t.
//----------------------------------------------------------------------------//
static function SkipLines( nToSkip )
local nSkipped := 0
DEFAULT nToSkip := 1
if nToSkip > 0
do while nSkipped < nToSkip .and. GoNextLine()
nSkipped++
enddo
elseif nToSkip < 0
do while nSkipped > nToSkip .and. GoPrevLine()
nSkipped--
enddo
endif
return nSkipped
//----------------------------------------------------------------------------//
static function GoToLine( nGoTo )
nGoTo := Max( 1, Min( nLines, nGoTo ) )
SkipLines( nGoTo - nLineNo )
return nil
//----------------------------------------------------------------------------//
static function CountCRLF()
local nCount := 0
local cBuf := Space( 10000 )
local nPrev := 0
local nRead
FSeek( hFile, 0, FS_SET )
REPEAT
nRead := FRead( hFile, @cBuf, 10000 )
nCount += Occurs( CRLF, Left( cBuf, nRead ) )
nLastAt := nPrev + RAt( CRLF, Left( cBuf, nRead ) ) + 1
nPrev += 10000
UNTIL nRead < 10000
return nCount
//----------------------------------------------------------------------------//Mr Adhemar
Just now I saw in the posting that the file is really huge.
Both the above alternatives work well for medium sized files, they may be somewhat slow for huge files.
The two time consuming parts of the code are (1) initial scan of the entire file for counting the number of lines and (2) skipping by large number of lines requiring reading of large buffers more than needed back and forth. ( Single line skips may be ok but skipping by large number of lines may be a little slow )
If the purpose is basically readonly it is more desirable to create an index table once and use it to browse whenever needed.

#include "FiveWin.ch"
#include "xbrowse.ch"
#include "fileio.ch"
#include "hbcompat.ch"
REQUEST DBFCDX
static hFile
//----------------------------------------------------------------------------//
function Main()
local oWnd, oBrw
local cTextFile := "c:\fwh\source\classes\xbrowse.prg"
local cIndexDbf
local c, k
cIndexDbf := cFileSetExt( cTextFile, "dbf" )
if ! File( cIndexDbf )
MsgRun( "Creating Index", "PLEASE WAIT", { || CreateIndexDbf( cTextFile, cIndexDbf ) } )
endif
hFile := FOpen( cTextFile )
USE ( cIndexDbf ) NEW ALIAS TDX SHARED READONLY VIA "DBFCDX"
DEFINE WINDOW oWnd
@ 0,0 XBROWSE oBrw OF oWnd DATASOURCE "TDX" ;
FIELDS RecNo(), ReadLine() ;
HEADERS "No", "Text" ;
PICTURES "9,999,999" ;
NOBORDER
WITH OBJECT oBrw
:nStretchCol := 2
:lVThumbTrack := .t.
//
:CreateFromCode()
END
oWnd:oClient := oBrw
ACTIVATE WINDOW oWnd
CLOSE TDX
FClose( hFile )
return 0
//----------------------------------------------------------------------------//
static function ReadLine()
local nRead, cLine
if FIELD->RECLEN == 0
return ""
endif
FSeek( hFile, FIELD->OFFSET, FS_SET )
cLine := Space( FIELD->RECLEN )
nRead := FRead( hFile, @cLine, FIELD->RECLEN )
return Left( cLine, nRead )
//----------------------------------------------------------------------------//
static function CreateIndexDbf( cFile, cDbf )
local hFile
local nBufSize := 32000
local cBuf := Space( nBufSize )
local nRead, nPrevRead := 0
local nAt, nLen
DbCreate( cDbf, {{ "OFFSET", 'N', 12, 0 }, { "RECLEN", 'N', 4, 0 }}, "DBFCDX", .t., "TDX" )
DbAppend()
FIELD->OFFSET := 0
hFile := FOpen( cFile )
do while .t.
nRead := FRead( hFile, @cBuf, nBufSize )
nAt := 1
do while ( nAt := At( CRLF, cBuf, nAt, nRead ) ) > 0
nLen := nAt + nPrevRead - FIELD->OFFSET - 1
FIELD->RECLEN := nLen
DBAPPEND()
nAt++
FIELD->OFFSET := nAt + nPrevRead
nAt++
enddo
if nRead < nBufSize
exit
else
nPrevRead += nBufSize
endif
enddo
FIELD->RECLEN := nRead + nPrevRead - FIELD->OFFSET
CLOSE TDX
return nil
//----------------------------------------------------------------------------//