Read the redirected input file in ANY order

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Read the redirected input file in ANY order

#1 Post by Aacini » 19 Jan 2012 13:05

In this topic I presented TYPEOFHANDLE.COM program that get status information from the standard handles. However, a .COM program may also modify certain handle status that persists after the .COM program ends; for example, the File Pointer position.

Code: Select all

SETFILEPOINTER handle position
This program move handle's File Pointer to the position given in bytes. Use 0 to BOF; use an E letter to indicate EOF.

SETFILEPOINTER program allows to read lines from the redirected input file in any order via the starting position of each line. These positions can be obtained just once and stored in an auxiliary file to be used several times:

Code: Select all

:CreateLinePositions
set position=0
:nextLine
   echo %position%
   set line=
   set /P line=
   call :StrLen line lineLen=
   set /A position+=lineLen+2
   TypeOfHandle 0
   set /A eof=%errorlevel% ^& 64
if %eof% == 0 goto nextLine
exit /B
File lines must end in CR+LF characters (Windows style) and must not have trailing control characters; also, they must not exceed the maximum SET /P input length of 1021 characters.

EDIT: I realized that previous process may be achieved in a simpler way via FINDSTR /O command this way:

Code: Select all

:CreateLinePositions
for /F "delims=:" %%a in ('findstr /O "^"') do echo %%a
exit /B

By convention, we will use .DEX extension for line-position files. For example, this data file:
Days.txt wrote:Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
... with this command:

Code: Select all

call :CreateLinePositions < Days.txt > lines.dex
... generate this index file:
lines.dex wrote:0
8
16
25
36
46
54
A data file may have several index files that allows to process the data in different orders. The following subroutine use the Bubble Sort method to sort the indexes of the lines, but does not modify the file itself:

Code: Select all

:BubbleSort baseIndex < inputFile > resultIndex
setlocal EnableDelayedExpansion
set n=0
for /F %%p in (%1) do (
   set /A n+=1
   set linePos[!n!]=%%p
)
:bubblePass
   set anyChange=
   set one=1
   setFilePointer 0 !linePos[1]!
   set /P line1=
   for /L %%i in (2,1,%n%) do (
      setFilePointer 0 !linePos[%%i]!
      set /P line2=
      if "!line1!" gtr "!line2!" (
         set /A temp=linePos[!one!], linePos[!one!]=linePos[%%i], linePos[%%i]=temp
         set "line2=!line1!"
         set anyChange=True
      )
      set /A one+=1
      set "line1=!line2!"
   )
if defined anyChange goto bubblePass
for /L %%i in (1,1,%n%) do echo !linePos[%%i]!
exit /B
For example, this command:

Code: Select all

call :BubbleSort lines.dex < Days.txt > alpha.dex
... create this index file:
alpha.dex wrote:46
8
54
0
36
16
25
... so this code:

Code: Select all

< Days.txt (
   for /F %%p in (alpha.dex) do (
      setFilePointer 0 %%p
      set /P line=
      echo !line!
   )
)
... display this result:
DaysInAlphaOrder.txt wrote:Friday
Monday
Saturday
Sunday
Thursday
Tuesday
Wednesday

A data file may also contain the position of a field located in another data file, like a rudimentary Relational Data Base (see this post).

This method also allows to modify data in a redirected output file in any place of the file, not just appending data at the end. To do that, just move the File Pointer of handle 1 to the desired position before output the new data:

Code: Select all

(
   setFilePointer 1 46
   echo Line 6
) >> Days.txt
Result:
Result wrote:Sunday
Monday
Tuesday
Wednesday
Thursday
Line 6
Saturday
Remember that the repetitive execution of .COM end .EXE executable programs is achieved faster if the DOS Window is maximized with Alt-Enter key. This is the complete SETFILEPOINTER.COM test program:

Code: Select all

@echo off
::SETFILEPOINTER.COM test program
::Antonio Perez Ayala - Jan/19/2012

setlocal EnableDelayedExpansion

if not exist SetFilePointer.com call :CreateSetFilePointer

cls

echo Days.txt:
(
echo Sunday
echo Monday
echo Tuesday
echo Wednesday
echo Thursday
echo Friday
echo Saturday
) > Days.txt
type Days.txt
echo/

echo lines.dex:
call :CreateLinePositions < Days.txt > lines.dex
type lines.dex
echo/

echo alpha.dex:
call :BubbleSort lines.dex < Days.txt > alpha.dex
type alpha.dex
echo/

echo DaysInAlphaOrder:
< Days.txt (
   for /F %%p in (alpha.dex) do (
      setFilePointer 0 %%p
      set /P line=
      echo !line!
   )
)
echo/

echo Line 6 of Days.txt modified:
(
   setFilePointer 1 46
   echo Line 6
) >> Days.txt
type Days.txt

goto :EOF


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


:CreateSetFilePointer
setlocal DisableDelayedExpansion
set SetFilePointer=2ÿ³‹û‹ó2íŠMÿãE° üó®t^>Š]ÿ€û0r6€û9w1€ë0Sã+€= u^&ó®t"Of3Àf3ɱ+€é!f3ÛGŠ]ÿ€ûEt+€ûeu(uÿë%%ëyGf3ÛŠ]ÿ€û0rs€û9wnf÷á€ë0f÷Ûf+ÃëáëØëäf‹È2Àf#ÉuTþÀþÀ€<EtK€<etFFÆDÿB‹Ñ±1€é!fÓé[´BÍ!r­€|ÿBu§±1€é!fÓâ‹Ðf÷Úf‹Ê±1€é!fÓé2ÀþÀþÀ´BÍ!2À´LÍ!ë¢ë½
setlocal EnableDelayedExpansion
echo !SetFilePointer!> SetFilePointer.com
exit /B


:CreateLinePositions < inputFile > baseIndex
for /F "delims=:" %%a in ('findstr /O "^"') do echo %%a
exit /B


:BubbleSort baseIndex < inputFile > resultIndex
setlocal EnableDelayedExpansion
set n=0
for /F %%p in (%1) do (
   set /A n+=1
   set linePos[!n!]=%%p
)
:bubblePass
   set anyChange=
   set one=1
   setFilePointer 0 !linePos[1]!
   set /P line1=
   for /L %%i in (2,1,%n%) do (
      setFilePointer 0 !linePos[%%i]!
      set /P line2=
      if "!line1!" gtr "!line2!" (
         set /A temp=linePos[!one!], linePos[!one!]=linePos[%%i], linePos[%%i]=temp
         set "line2=!line1!"
         set anyChange=True
      )
      set /A one+=1
      set "line1=!line2!"
   )
if defined anyChange goto bubblePass
for /L %%i in (1,1,%n%) do echo !linePos[%%i]!
exit /B
Last edited by Aacini on 14 Apr 2014 09:26, edited 2 times in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Read the redirected input file in ANY order

#2 Post by Ed Dyreen » 19 Jan 2012 13:15

'
I use to read ini files a lot, I use the [ ] for pattern search and replace.

Can't use this right now but, dBenham points out, someday I might run into problems with findstr.EXE so maybe...

Pretty cool :wink: :!:

Post Reply