Check if a file is a valid SQLite database

2019-03-06 04:36发布

问题:

I need to check whether a file (with unknown extension) is a valid SQLite database.

My function works fine, but when it fails, the file is still locked after exiting the function:

Public Function IsSqliteDB(ByVal uPath As String) As Boolean

    'Workaround for my problem: Make a copy and work on this because this function is going to lock the file unfortunately
    Dim sNewPath As String
    sNewPath = Settings.Locations.Folder_LocalAppData_Temp & "\temp_" & Replace(Now.ToString, ":", "_") & ".db"

    modIO.FileForceCopy(uPath, sNewPath)

    Dim bIsSQLiteDB As Boolean = False

    Dim c As New dhRichClient3.cConnection
    Dim r As dhRichClient3.cRecordset


    Try
        Dim b As Boolean = c.OpenDB(sNewPath) 'returns true although this is not an sqlite-db. Can't do anything about it
        R = c.OpenRecordset("SELECT * FROM sqlite_master")
        bIsSQLiteDB = True

    Catch ex As Exception
        r = Nothing
        c = Nothing
    Finally
        r = Nothing
        c = Nothing
    End Try

    modIO.DeleteFile(sNewPath)'this fails. File is locked

    Return bIsSQLiteDB

End Function

Does anybody see where I could ensure that the file is not locked anymore? Or do I really have to work with a copy of the file because the behaviour of the COM component is not really known (closed source unfortunately)? I could indeed work with a backup, but the file may be really large (> 1 GB), so I would like to avoid making a copy to work on if I could avoid it.

There is no "close" function in dhRichClient. "Close" is called internally once the cConection goes out out scope, I guess. Calling GC.Collect() at the end of the function does not help.

回答1:

To determine if a file is an SQLite database, just check the first 16 bytes of the database header.

from tmighty's comment:

Public Function IsSqliteDB(ByVal uPath As String) As Boolean
    Dim bytes(16) As Byte
    Using fs As New IO.FileStream(uPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
        fs.Read(bytes, 0, 16)
    End Using
    Dim text As String = System.Text.ASCIIEncoding.ASCII.GetString(bytes)
    Return text.Contains("SQLite format")
End Function