0

私は VB.NET webforms サイトを作成しています。その 1 ページでファイルのリストをリストボックスにロードする必要があります。データベースにエントリがないディレクトリ内のすべての PDF および TIF ファイルをロードする必要があります。現在、次のコードを使用してこれを正常に実行しています。基本的に、データベースにクエリを実行してファイル名エントリの配列リストを取得し、ディレクトリ内の各ファイルを調べて、その名前を配列リストの各エントリと照合し、その名前が配列リストにない場合は、リストに追加してバインドしますリストボックス:

    Dim category As String = "RFQ"

    'Initialize database connection variables
    Dim sql As String
    Dim query As System.Data.SqlClient.SqlCommand
    Dim result As System.Data.SqlClient.SqlDataReader

    'Load document list from database
    Dim savedfiles As New ArrayList
    database.Open() 'Open connection to database  
    sql = "SELECT filename FROM fileheaders WHERE [category] = '" & category & "'" 'SQL query to read file header information
    query = New System.Data.SqlClient.SqlCommand(sql, database) 'Create query to send to database
    result = query.ExecuteReader() 'Execute query
    While result.Read()
        savedfiles.Add(row(result, "filename"))
    End While
    result.Close()
    dbDocscan.Close()


    'The following code section pulls all files from the current file directory.
    Dim filelist = New ArrayList
    Dim dir As New System.IO.DirectoryInfo(dirName) 'Get directory information
    Dim files As System.IO.FileInfo() = dir.GetFiles() 'Get all files in directory
    Dim file As System.IO.FileInfo
    Dim i As Integer = 0
    For Each file In files
        If ((file.Extension Like ".pdf") Or (file.Extension Like ".tif")) And Not inArray(savedfiles, file.Name) Then
            filelist.Add(file.Name) 'Add .pdf and .tif files to list of documents
        End If
    Next

    filelist.TrimToSize()
    eltFilelist.DataSource = filelist
    eltFilelist.DataBind() 'Bind document list to listbox

次に、inArray 関数コード:

Function inArray(arr As ArrayList, str As String) As Boolean
    For Each item In arr
        If TypeOf (item) Is String Then
            If str = item Then
                Return True
                Exit Function
            End If
        End If
    Next
    Return False
End Function

ここに問題があります。機能している一方で、非常に効率が悪いようです。ディレクトリには約 27,000 個のファイルがあり、データベースには約 26,000 個のファイル エントリがあります。したがって、26,000 の名前のリストに対して 27,000 のファイル名のそれぞれをチェックしています。これを組み合わせの問題にしないと、何億もの文字列一致ステートメントになります。これについてもっと効率的な方法はありますか?

4

2 に答える 2

0

SQL パラメータを使用して、カテゴリ文字列の問題を回避し (たとえば、アポストロフィが含まれていると、連結されたクエリ文字列が壊れてしまいます)、目的の拡張子を持つディレクトリ内のファイルのみを取得できます。 LINQ を使用して不足しているファイルを簡単な方法で取得できます。

Imports System.Data.SqlClient
Imports System.IO
Module Module1
    Function GetMissingFiles(sourceDirectory As String, category As String) As List(Of String)
        Dim missingFiles As New List(Of String)

        Dim filesInDatabase As New List(Of String)

        ' Query the database for the files in the given category'
        Using conn As New SqlConnection("connection string here")
            conn.Open()
            Dim sqlCmd As String = "SELECT filename FROM fileheaders WHERE [category] = @category"
            Dim query As New System.Data.SqlClient.SqlCommand(sqlCmd, conn)
            'TODO: change .SqlDbType to what it is in the database.'
            query.Parameters.Add(New SqlParameter With {.ParameterName = "@category", .SqlDbType = SqlDbType.NVarChar, .Value = category})

            Dim rdr As SqlDataReader = query.ExecuteReader()

            While rdr.Read()
                filesInDatabase.Add(rdr.GetString(0))
            End While

            conn.Close()

        End Using

        'TODO: it could be that filesInDatabase.Count = 0 is valid. Adjust if required.'
        If filesInDatabase.Count > 0 Then
            ' Get the existing files from the given directory.

            ' the extensions we are going to consider
            Dim extensions() As String = {"pdf", "tif"}

            Dim existingFiles As New List(Of String)

            ' get all the filenames (without the path) to consider'
            For Each extn In extensions
                existingFiles.AddRange(Directory.GetFiles(sourceDirectory, "*." & extn).ToList().Select(Function(p) Path.GetFileName(p)))
            Next

            missingFiles = existingFiles.Except(filesInDatabase).ToList()

        End If

        Return missingFiles

    End Function
    Sub Whatever()
        Dim myMissingFiles As List(Of String)
        Try
            myMissingFiles = GetMissingFiles("C:\temp", "RFQ")
        Catch ex As Exception
            ' Inform user it went wrong.'
        End Try

        If myMissingFiles IsNot Nothing AndAlso myMissingFiles.Count > 0 Then
            eltFilelist.DataSource = myMissingFiles
            eltFilelist.DataBind()
        End If

    End Sub

End Module
于 2013-08-27T21:35:45.720 に答える
0

ArrayList を使用する代わりに、Dictionary または HashTable を使用して、クエリからファイル名を保存します。

inArray 関数は、見つかったすべてのファイルに対して O(n) テーブル スキャンを実行していますが、これは非常に低速です。

Dictionaries と HashTables の両方に、ファイル名を大幅に高速で検索する Contains メンバーがあります。

于 2013-08-27T20:13:15.980 に答える