Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!dali.cs.montana.edu!caen!zaphod.mps.ohio-state.edu!wuarchive!ukma!psuvax1!hsdndev!cmcl2!adm!news From: CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) Newsgroups: comp.lang.pascal Subject: Re: Text Files, I/O Redirection Message-ID: <27007@adm.brl.mil> Date: 24 May 91 13:50:18 GMT Sender: news@adm.brl.mil Lines: 148 In article 45670018@hpcupt3.cup.hp.com, defaria@hpcupt3.cup.hp.com (Andy DeFaria) wrote: [... scattered deletions throughout ...] >2) How do you get the name of an open text file from AFile : Text > variable? > >3) The FileSize function doesn't work on Text files. How can I > easily and efficiently get the FileSize (in bytes) of a Text > file? >I have solved #2 and #3. The solution for #2 is to cast the Text >file to a TextRec and extract the Name field. Unfortunately this >The solution to #3 is a little bit uglier but works. Basically, I >take the Text file, get its name (see above), assign it to a File >of Byte and call FileSize on that file (Oh and don't forget to >Close the file). I would like to come up with a better method >for this. I don't like opening and closing files if I can avoid Unfortunately, that "solution" to #3 overlooks the text currently in the file's buffer (within the TextRec). This doesn't matter if you aren't currently writing the file. _My_ solution to this problem is to use routines from TurboPower Software. ;) However, for your use I offer this: Again casting the text file as a TextRec, extract the Handle and BufPos values. With a registers variable, call MSdos with ah := $42, al := 1, bx := Handle, and cx and dx := 0. The current position of the DOS file pointer will return in dx and ax. Save it as fpos := longint(dx) shl 16 + ax. If you are writing the file, the true size, including buffered output, should be fpos + BufPos. If you are reading the file, you need to do a DOS seek to EOF. Don't forget to save fpos, because you'll need it to restore the file pointer. Call MSdos again with ah := $42, al := 2, bx := Handle, cx and dx := 0. The current DOS file size will return in dx and ax as before. That should be the true size. Now call MSdos with ah := $42, al := 0, bx := Handle, cx := fpos shr 16, dx := fpos and $FFFF. This will return the file pointer to the original position. Here's code for making the actual DOS calls. Note that this code knows nothing about text files and doesn't set TPas' InOutRes, so you have to pay attention to the function returns to detect a file io error. =========================== cut here ============================ const {base of DOS file seek} baseSOF = 0; {seek from start of file} baseCurPos = 1; {seek from current file pointer} baseEOF = 2; {seek from end of file} function DosFilePos(handle : word; var fpos : longint) : integer; { Call DOS to determine the absolute position of the file pointer IN BYTES from the beginning of the file. Remember that DOS knows nothing of file contents that may be buffered with Turbo Pascal: this file pointer is the one DOS keeps, and may differ from Turbo Pascal's buffered file pointer within a text file. Return the error code. If no error, return the absolute position of the file pointer IN BYTES in fpos. } var regs : Registers; begin {DosFilePos} with regs do begin ah := $42; al := baseCurPos; bx := handle; cx := 0; dx := 0; MSdos(regs); if (flags and FCarry) = FCarry then {error} DosFilePos := ax else begin DosFilePos := 0; fpos := longint(dx) shl 16 + ax; end; {no error} end; {with regs} end; {DosFilePos} function DosFileSeek(handle : word; base : word; var fpos : longint) : integer; { Call DOS to do a seek of the offset fpos IN BYTES from the specified base (see constants above). Return the error code. If no error, return the new absolute position of the file pointer IN BYTES in fpos. } var regs : registers; begin {DosFileSeek} with regs do begin ah := $42; al := base; bx := handle; cx := fpos shr 16; dx := fpos and $FFFF; MSdos(regs); if (flags and FCarry) = FCarry then {error} DosFileSeek := ax else begin DosFileSeek := 0; fpos := longint(dx) shl 16 + ax; end; {no error} end; {with regs} end; {DosFileSeek} function DosFileSize(handle : word; var fsize : longint) : integer; { Call DOS to get the size of the file. Return the error code. If no error code, return the file size IN BYTES in fsize. This calls DosFilePos and DosFileSeek and is subject to the same caveats re text files and buffers. } var pos : longint; res : integer; begin {DosFileSize} pos := 0; res := DosFilePos(handle,pos); {get current offset} fsize := 0; if res = 0 then res := DosFileSeek(handle,baseEOF,fsize); {seek to EOF} DosFileSize := res; res := DosFileSeek(handle,baseSOF,pos); {restore original offset} end; {DosFileSize} =========================== cut here ============================ (BTW--this code is relatively new and I would urge any users to consider it Not Adequately Tested. It is in the public domain.) Cheers-- --Karl +====================================================================+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta GA 30093 USA | | Home of Epi Info 5.0 | +====================================================================+