TruncateFile.exe: Truncate a data file at any size

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

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

TruncateFile.exe: Truncate a data file at any size

#1 Post by Aacini » 09 Nov 2014 22:02

After completed my GetFileType.exe auxiliary program, I reviewed the rest of WIN-32 API functions of that type looking for another one useful for Batch files, and found it: SetEndOfFile. This function allows to truncate a data file at any given size, but it requires that the file pointer of the file handle be placed at the truncation point. This means that, in order to use TruncateFile.exe auxiliary program in a Batch file, you need to also use FilePointer.exe one; just download it from this post.

The Batch file below create the new TruncateFile.exe auxiliary program and describe how to use it.

Code: Select all

@echo off
setlocal EnableDelayedExpansion

rem TruncateFileDoc.bat: Create TruncateFile.exe auxiliary program and describe it
rem Antonio Perez Ayala

if not exist TruncateFile.exe (
   echo Extracting TruncateFile.exe
   call :ExtractBinaryFile TruncateFile.exe
   echo TruncateFile.exe file created
   echo/
)

echo Truncate the file of the given handle at the current file pointer position.
echo/
echo    TruncateFile.exe handle
echo/
echo The result is reported via ERRORLEVEL this way:
echo/
echo -2      No handle given or bad handle number.
echo -1      The handle number is not connected to any file.
echo  0      File truncated correctly.
echo  1      Error while trying to truncate the file.
echo/
echo To see an example, review the code of this program (%~NX0);
echo the following is the output example.
echo/
echo Original contents of the data file:
echo ===================================
type TruncateFile.txt
echo ===================================

< TruncateFile.txt (
   rem Locate the last permanent line in the file (from STDIN)
   call :LocateLastLine
   rem Get current FilePointer position
   FilePointer 0 0 /C
   set filePointer=!errorlevel!
)

(
   rem Set FilePointer position after last permanent line (to STDOUT)
   FilePointer 1 !filePointer!
   rem Truncate the file at this point
   TruncateFile.exe 1
) >> TruncateFile.txt


rem Add new lines at end of truncated data
echo This is new data added after the last permanent line in the file >> TruncateFile.txt

echo/
echo/
echo New contents of the data file:
echo ===================================
type TruncateFile.txt
echo ===================================

goto :EOF


:LocateLastLine
set /P line=
if "%line:~0,6%" neq "EOPD: " goto LocateLastLine
exit /B


rem Extract Binary File from hexadecimal digits placed in a "resource" in this .bat file

:ExtractBinaryFile filename.ext[.cab]
setlocal EnableDelayedExpansion
set "start="
set "end="
for /F "tokens=1,3 delims=:=>" %%a in ('findstr /N /B "</*resource" "%~F0"') do (
   if not defined start (
      if "%%~b" equ "%~1" set start=%%a
   ) else if not defined end set end=%%a
)
(for /F "skip=%start% tokens=1* delims=:" %%a in ('findstr /N "^" "%~F0"') do (
   if "%%a" == "%end%" goto decodeHexFile
   echo %%b
)) > "%~1.hex"
:decodeHexFile

rem Modified code based on :genchr subroutine
type nul > t.tmp
(for /F "usebackq" %%a in ("%~1.hex") do (
   set input=%%a
   set i=0
   for /L %%I in (0,2,120) do for %%i in (!i!) do if "!input:~%%i,1!" neq "" (
      set hex=!input:~%%i,2!
      set /A i+=2
      if "!hex:~0,1!" neq "[" (
         set /A chr=0x!hex!
         if not exist !chr!.chr call :genchr !chr!
         type !chr!.chr
      ) else (
         for /L %%J in (1,1,5) do for %%i in (!i!) do if "!input:~%%i,1!" neq "]" (
            set "hex=!hex!!input:~%%i,1!"
            set /A i+=1
         )
         if not exist 0.chr call :genchr 0
         for /L %%J in (1,1,!hex:~1!) do type 0.chr
         set /A i+=1
      )
   )
)) > "%~1"
del *.chr
del t.tmp temp.tmp
del "%~1.hex"

rem Expand created file if extension is .cab
set "filename=%~1"
if /I "%filename:~-4%" equ ".cab" (
   expand "%filename%" "%filename:~0,-4%" > NUL
   del "%filename%"
)

exit /B


:genchr
REM This code creates one single byte. Parameter: int
REM Teamwork of carlos, penpen, aGerman, dbenham
REM Tested under Win2000, XP, Win7, Win8
set "options=/d compress=off /d reserveperdatablocksize=26"
if %~1 neq 26 (
   makecab %options% /d reserveperfoldersize=%~1 t.tmp %~1.chr > nul
   type %~1.chr | ( (for /l %%N in (1,1,38) do pause)>nul & findstr "^" > temp.tmp )
   >nul copy /y temp.tmp /a %~1.chr /b
) else (
   copy /y nul + nul /a 26.chr /a >nul
)
exit /B


<resource id="TruncateFile.exe">
4d5a900003[3]04[3]ffff[2]b8[7]40[35]b0[3]0e1fba0e00b409cd21b8014ccd21546869732070726f6772616d2063616e6e6f74206265207275
6e20696e20444f53206d6f64652e0d0d0a24[7]551e49c1117f2792117f2792117f27929f603492167f2792ed5f3592137f279252696368117f2792
[8]5045[2]4c01020094146054[8]e0000f010b01050c0002[3]02[7]10[3]10[3]20[4]40[2]10[3]02[2]04[7]04[8]30[3]02[6]03[5]10[2]10
[4]10[2]10[6]10[11]1420[2]28[84]20[2]14[27]2e74657874[3]96[4]10[3]02[3]02[14]20[2]602e7264617461[2]9e[4]20[3]02[3]04[14]
40[2]40[8]e84b[3]e86a[3]33c048488a1e80fb30722980fb39772480e30fb8f6ffffff2ac350e85a[3]0bc07c1050e856[3]0bc0b8[4]75014050
e83a[3]cccccccccccccccccccccccce83b[3]8bf08a06463c2275098a06463c2275f9eb0c8a06463c20740484c075f54ec38a06463c2074f94ec3cc
ff250c204000ff2500204000ff2504204000ff25082040[363]5e20[2]6e20[2]7e20[2]5020[6]3c20[10]9020[3]20[22]5e20[2]6e20[2]7e20[2]
5020[6]9b004578697450726f63657373006a0147657453746448616e646c65[2]7c02536574456e644f6646696c65[2]e600476574436f6d6d616e64
4c696e6541006b65726e656c33322e646c6c[356]
</resource>

Using this data file TruncateFile.txt:

Code: Select all

This file contains several permanent lines at beginning.

The next line is the last permanent one.
EOPD: End Of Permanent Data
This is the first line that will be changed.

The rest of this data will be removed...

... this is the output of previous program:

Code: Select all

C:\> TruncateFileDoc.bat
Truncate the file of the given handle at the current file pointer position.

   TruncateFile.exe handle

The result is reported via ERRORLEVEL this way:

-2      No handle given or bad handle number.
-1      The handle number is not connected to any file.
 0      File truncated correctly.
 1      Error while trying to truncate the file.

To see an example, review the code of this program (TruncateFileDoc.bat);
the following is the output example.

Original contents of the data file:
===================================
This file contains several permanent lines at beginning.

The next line is the last permanent one.
EOPD: End Of Permanent Data
This is the first line that will be changed.

The rest of this data will be removed...
===================================


New contents of the data file:
===================================
This file contains several permanent lines at beginning.

The next line is the last permanent one.
EOPD: End Of Permanent Data
This is new data added after the last permanent line in the file
===================================


Antonio

Post Reply