Announcement

Collapse
No announcement yet.

Getting a filesize on read-only drives

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting a filesize on read-only drives

    Hi,
    Can anyone tell us how to return the size of a single file?

    The below code works, but if the file is not present it creates a zero-length file with the name of the one we were checking for, so it presumably wouldn't work on a read-only network or an optical drive.

    Code:
    SUB TestSub() 
    
    Local Shellline As String
    LOCAL FileSize AS QUAD
    
    'in the final version, this value will be read from an INI file
    Shellline="q:\factory\metalwork\fanuc\OMD\transfer.exe"
    
    OPEN Shellline FOR BINARY AS #1
    FileSize = LOF(1)
    CLOSE #1
    
    'PrintQuad shows the returned value in a textbox
    PrintQuad FileSize
    Thanks in advance to anyone that can help.

  • #2
    http://www.powerbasic.com/support/pb...ad.php?t=35981

    Check "my" code near the bottom of the 1st page. The example returns the total size for all files matching specs but it should show you how to return for a single file.
    There are no atheists in a fox hole or the morning of a math test.
    If my flag offends you, I'll help you pack.

    Comment


    • #3
      Originally posted by Chris Burgess View Post
      Hi,
      Can anyone tell us how to return the size of a single file?

      The below code works, but if the file is not present it creates a zero-length file with the name of the one we were checking for, so it presumably wouldn't work on a read-only network or an optical drive.
      ...
      In that case wouldn't the Sub return an ERROR code? (or at least the Open statement) Presumably you have an
      Code:
      If Err Then ...
      somewhere in the neighborhood.

      ===========================
      An investment in knowledge
      pays the best interest.
      Ben Franklin
      ===========================
      It's a pretty day. I hope you enjoy it.

      Gösta

      JWAM: (Quit Smoking): http://www.SwedesDock.com/smoking
      LDN - A Miracle Drug: http://www.SwedesDock.com/LDN/

      Comment


      • #4
        Try
        Code:
        OPEN Shellline FOR BINARY ACCESS READ AS #1
        Rgds, Dave

        Comment


        • #5
          CC5+, WIN 9+
          Code:
          LOCAL DD AS DIRDATA 
           S = DIR$ (filename) TO DD 
           File_Size =  DD.FilesizeLow  
           DIR$ CLOSE
          Michael Mattias
          Tal Systems (retired)
          Port Washington WI USA
          [email protected]
          http://www.talsystems.com

          Comment


          • #6
            Gösta:
            Presumably you have an If Err Then somewhere in the neighborhood.
            Hi, thanks for your reply.
            I added Err to detect this condition, but have since found another issue with it. On a read-only drive, it returns an error 52 (bad file name or number), which can be used to detect this OK.

            The issue now is that the code can't differentiate between a valid zero-length file or the new file it creates if the file is not present. It shouldn't be too hard to do this by using GETATTR and immidiately checking for Err 53 though. I'll have a go tonight.
            Thanks for the reply.
            Chris



            Dave:
            OPEN Shellline FOR BINARY ACCESS READ AS #1
            This still creates the zero length file, if the file with that name does not exist when the call was made. I'm about to try using GETATTR to see if the file exists first.


            Michael:
            LOCAL DD AS DIRDATA
            Is this CC5 only code, or can this be made to work with PBW/8?
            I'm nor sure what you mean be "DIRDATA", I was under the impression that when a variable is declared "AS" a certain type, it had to be a specific data type, such as STRING, INTEGER, WORD, etc.
            I tried it anyway, but it choked in the above line, as I semi-expected.

            Regards,
            Chris

            Comment


            • #7
              DirData is internally defined in PBWIN9 and PB5.
              DIR$ has been improved
              Thanks Michael for showing the code.
              Last edited by Mike Doty; 6 Apr 2009, 09:11 AM.
              How long is an idea?

              Comment


              • #8
                DIR$ function

                Purpose
                Return a filename and/or directory entry that matches a file name mask and an optional attribute.
                Syntax
                file$ = DIR$(mask$ [, [ONLY] attribute&, TO DirDataVar])
                file$ = DIR$([NEXT] [TO DirDataVar])

                The DIR$ function may optionally assign the complete directory entry to an appropriate UDT variable if you include the TO clause as a parameter. The complete directory entry contains 318 bytes of data, corresponding to the following TYPE definition. This definition (DIRDATA) is built into PowerBASIC, and need not necessarily be included in your source code.
                TYPE DirData
                ..FileAttributes AS DWORD
                ..CreationTime AS QUAD
                ..LastAccessTime AS QUAD
                ..LastWriteTime AS QUAD
                ..FileSizeHigh AS DWORD
                ..FileSizeLow AS DWORD
                ..Reserved0 AS DWORD
                ..Reserved1 AS DWORD
                ..FileName AS ASCIIZ * 260
                ..ShortName AS ASCIIZ * 14
                END TYPE


                TYPE WIN32_FIND_DATA
                dwFileAttributes AS DWORD
                ftCreationTime AS FILETIME
                ftLastAccessTime AS FILETIME
                ftLastWriteTime AS FILETIME
                nFileSizeHigh AS DWORD
                nFileSizeLow AS DWORD
                dwReserved0 AS DWORD
                dwReserved1 AS DWORD
                cFileName AS ASCIIZ * %MAX_PATH
                cAlternateFileName AS ASCIIZ * 14
                END TYPE
                Last edited by Mike Doty; 6 Apr 2009, 08:39 AM.
                How long is an idea?

                Comment


                • #9
                  Rewrote as SUB because DWORD can't return a negative number to indicate not found in a function.

                  The range is only 0 to 4,294,967,295 bytes.

                  Code:
                  SUB FileSize(BYVAL f AS STRING, TheSize AS DWORD,Found AS LONG)
                    LOCAL FindData AS WIN32_FIND_DATA
                    LOCAL hDir AS LONG
                    hDir = FindFirstFile(BYVAL STRPTR(f), FindData)
                    IF hDir = -1 THEN  
                      TheSize = 0
                      Found =  0
                    ELSE
                      Found = 1
                      FindClose hDir
                      TheSize = FindData.nFileSizeLow
                    END IF
                  END SUB
                  Last edited by Mike Doty; 6 Apr 2009, 02:32 PM. Reason: DWORD can't return a negative number, added Found
                  How long is an idea?

                  Comment


                  • #10
                    http://www.powerbasic.com/support/pb...ad.php?t=34824
                    Last edited by Mike Doty; 6 Apr 2009, 03:27 PM.
                    How long is an idea?

                    Comment


                    • #11
                      Code:
                      FUNCTION FileSize(BYVAL f AS STRING) AS QUAD
                        LOCAL FindData AS WIN32_FIND_DATA
                        LOCAL hDir AS LONG
                        hDir = FindFirstFile(BYVAL STRPTR(f), FindData)
                        IF hDir = -1 THEN  'if not found return -1
                          FUNCTION = -1
                        ELSE               'return number of bytes
                          FindClose hDir
                          FUNCTION = MAK(QUAD, FindData.nFileSizeLow , FindData.nFileSizeHigh)
                        END IF
                      END FUNCTION
                      Last edited by Mike Doty; 6 Apr 2009, 03:26 PM. Reason: Tested on a 99 billion-byte file
                      How long is an idea?

                      Comment


                      • #12
                        Nice one Mike - That's a keeper!
                        Rgds, Dave

                        Comment


                        • #13
                          Filesize

                          Does PB have a file size routine?
                          Tested with Windows 7.

                          Code:
                          %MAX_PATH  = 260  ' max. length of full pathname
                          '------------------------------------------------------------------------------
                          TYPE FILETIME
                            dwLowDateTime AS DWORD
                            dwHighDateTime AS DWORD
                          END TYPE
                          '------------------------------------------------------------------------------
                          TYPE WIN32_FIND_DATA
                            dwFileAttributes AS DWORD
                            ftCreationTime AS FILETIME
                            ftLastAccessTime AS FILETIME
                            ftLastWriteTime AS FILETIME
                            nFileSizeHigh AS DWORD
                            nFileSizeLow AS DWORD
                            dwReserved0 AS DWORD
                            dwReserved1 AS DWORD
                            cFileName AS ASCIIZ * %MAX_PATH
                            cAlternateFileName AS ASCIIZ * 14
                          END TYPE
                          '------------------------------------------------------------------------------
                          DECLARE FUNCTION FindFirstFile LIB "KERNEL32.DLL" ALIAS "FindFirstFileA" _
                                  (lpFileName AS ASCIIZ, lpFindFileData AS WIN32_FIND_DATA) AS DWORD
                          '------------------------------------------------------------------------------
                          DECLARE FUNCTION FindClose LIB "KERNEL32.DLL" ALIAS "FindClose" _
                                  (BYVAL hFindFile AS DWORD) AS LONG
                          '------------------------------------------------------------------------------
                          FUNCTION PBMAIN AS LONG
                            ? FORMAT$(FileSize("c:\windows\system32\mrt.exe"),"#,")
                            REM CreateKillTest
                          END FUNCTION
                          '------------------------------------------------------------------------------
                          FUNCTION FileSize(BYVAL sFileName AS STRING) AS QUAD
                            REM Usage:  Bytes = FileSize(sFileName)
                            REM         Returns -1 if not found
                           
                            LOCAL FindData       AS WIN32_FIND_DATA
                            LOCAL hDir           AS LONG
                            LOCAL sInvalidChars  AS STRING
                           
                            'sInvalidChars = "\/:*?""<>|"  'first character may be \
                            hDir = FindFirstFile(BYVAL STRPTR(sFileName), FindData)
                            IF hDir = -1 THEN  'if not found return -53
                              FUNCTION = -53
                            ELSE               'return number of bytes
                              FindClose hDir
                              FUNCTION = MAK(QUAD, FindData.nFileSizeLow , FindData.nFileSizeHigh)
                            END IF
                          END FUNCTION
                          '------------------------------------------------------------------------------
                          FUNCTION CreateKillTest AS LONG
                           
                            'Create and kill a temp file to test filesize routine
                            LOCAL sFile  AS STRING
                            LOCAL qBytes AS QUAD
                            LOCAL hFile  AS LONG
                            sFile = "\junk.tmp" 'creates and deletes this file
                            qBytes = 0          'quad supported
                           
                            'Test
                            hFile = FREEFILE
                            OPEN sFile FOR BINARY AS #hFile
                            IF ERR THEN ? "Unable to open " + sFile + " error" + STR$(ERRCLEAR):EXIT FUNCTION
                            SEEK #hFile, qBytes +1
                            IF ERR THEN ? "Unable to seek to byte" + STR$(qBytes) + " error" + STR$(ERRCLEAR):EXIT FUNCTION
                            SETEOF #hFile
                            IF ERR THEN ? "Unable to SETEOF, error" + STR$(ERRCLEAR):CLOSE #hFile:EXIT FUNCTION
                            ? sFile + " contains " +  FORMAT$(FileSize(sFile),"#,") + " bytes with file open."
                            CLOSE #hFile
                            ? sFile + " contains " +  FORMAT$(FileSize(sFile),"#,") + " bytes with file closed."
                            KILL sFile
                            IF ERR THEN
                              ? "Unable to kill " + sFile + " error" + STR$(ERRCLEAR)
                            ELSE
                              ? "Killed " +sFile
                            END IF
                            #IF %DEF(%PB_CC32)
                               ? "Press any key to exit"
                               WAITKEY$
                            #ENDIF
                          END FUNCTION
                          How long is an idea?

                          Comment


                          • #14
                            Other than LOF function? Improved DIR$ can return a UDT containing members FileSizeHigh and FileSizeLow dword members.

                            Cheers,
                            Dale

                            Comment


                            • #15
                              " var = FILESIZE(filespec) " sure sounds like a New Feature Suggestion waiting for someone to submit it.
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                No api calls

                                Code:
                                FUNCTION PBFileSize(BYVAL sFile AS STRING) AS QUAD
                                 
                                  LOCAL Udt AS DIRDATA         'DIRDATA built into PowerBASIC
                                  sFile = DIR$ (sfile TO Udt)  'fill structure
                                  DIR$ CLOSE                   'Michael Mattias.  see post below
                                  IF LEN(sFile) THEN           'file found
                                    FUNCTION = MAK(QUAD, Udt.FileSizeLow , Udt.FileSizeHigh)'make quad
                                  ELSE
                                    FUNCTION = -53             'not found, return error -53
                                  END IF
                                 
                                END FUNCTION
                                 
                                FUNCTION PBMAIN AS LONG
                                 
                                  LOCAL sFile AS STRING
                                  LOCAL qSize AS QUAD
                                 
                                  sFile = "c:\windows\system32\mrt.exe"
                                  qSize = PBFileSize(sFile)
                                  ? USING$("#,",qSize)
                                 
                                END FUNCTION
                                Last edited by Mike Doty; 25 Aug 2010, 12:16 PM.
                                How long is an idea?

                                Comment


                                • #17
                                  You should add a DIR$ CLOSE to that function.

                                  While it won't make a difference in most cases, the open search handle (from DIR$) will prevent you from deleting or renaming the directory elsewhere in your program.

                                  (Any subsequent call to DIR$ (on this thread) will automatically close the original handle, but IMO it's better to just "release what you get" in the procedure).

                                  MCM
                                  Michael Mattias
                                  Tal Systems (retired)
                                  Port Washington WI USA
                                  [email protected]
                                  http://www.talsystems.com

                                  Comment


                                  • #18
                                    DIR$ CLOSE added - thank you Michael Mattias

                                    Good catch, thank you!
                                    Modified here and in the source code forum.

                                    http://www.powerbasic.com/support/pb...ad.php?t=44442
                                    How long is an idea?

                                    Comment


                                    • #19
                                      Odd!
                                      This file "C:\Windows\System32\MRT.exe" does appear in Explorer and I can use DIR with it in a CMD window..
                                      Directory of C:\Windows\System32

                                      03/08/2010 11:52 AM 37,437,384 MRT.exe
                                      1 File(s) 37,437,384 bytes
                                      It doesn't show up in the test program though? The message box reports "-53".

                                      I tried using IsFile() against it - again not found.
                                      Other files in the same directory are found both by IsFile() and PBFileSize() - "C:\Windows\System32\MRINFO.exe" for example.

                                      I'm using Win7 with an 'administrator' account and have tried running the test program with the "Run as Adminstrator" option. Tried running in XPMode - same -53 result .
                                      Last edited by Dave Biggs; 25 Aug 2010, 10:00 PM.
                                      Rgds, Dave

                                      Comment


                                      • #20
                                        Would you please report what this reports from a CMD window:
                                        ATTRIB c:\windows\system32\mrt.exe

                                        I tested with 32-bit Windows 7 and it works.
                                        I will test with 64-bit Windows 7 in a few minutes.

                                        Not working with 64-bit Windows 7. Investigating.
                                        Last edited by Mike Doty; 25 Aug 2010, 10:20 PM.
                                        How long is an idea?

                                        Comment

                                        Working...
                                        X