Эффективно добавлять файлы .csv вместе (VB.NET) - PullRequest
0 голосов
/ 11 июля 2019

У меня есть вопрос, касающийся фрагмента кода, который я хотел бы сделать более эффективным в Visual Basic.Я пытаюсь сделать следующее:

  • У меня есть папка, содержащая 100 файлов .csv (через запятую), эти файлы содержат около 5000 строк и около 200 столбцов.Порядок столбцов может варьироваться от одного файла к другому, и некоторые столбцы отсутствуют в некоторых файлах.
  • Моя цель - создать один большой файл .csv, который объединяет все 100 файлов .csv с выборомстолбец, который я указываю заранее.
  • Вот как я продолжаю:

    1. Создайте массив для хранения имени столбцов, которые я хочу в конечном «большом .csv»”
    2. Перебрать все файлы в папке.Для каждого файла
    3. Для каждой строки в файле используйте функцию Split, чтобы создать массив, содержащий все значения для данной строки.
    4. создайте массив отображения, в котором будет храниться позициястолбца в файле для каждого имени столбца, выбранного на первом шаге (сделать это только для первой строки каждого файла)
    5. Записать в файл («большой .csv») заголовок (сделать этотолько один раз)
    6. Записать в один и тот же большой файл для каждой строки каждого файла данные, основанные на положении столбца.

, чтобыпроцесс работает хорошо, я получаю желаемый результат, но он очень медленный… (На моем компьютере требуется ~ 40 минут для ~ 200 файлов, которые после добавления содержат 500 000 строк и 200 столбцов. Коллеге удалось выполнить аналогичный процесс, добавиввсе файлы, используя пакет data.table в R, и он может выполнить то же добавление с теми же таблицами .csv за 5-10 минут на одном компьютере). Мне было интересно, есть ли лучшая альтернатива, чемПройдя через файл «ячейка за ячейкой»?Могу ли я определить столбец, который мне не нужен, из исходного файла и удалить их полностью?Есть ли функция, позволяющая добавлять файлы вместе, а не читать каждую ячейку, а затем записывать их обратно?

Редактировать: В качестве альтернативы, существует ли другой язык программирования, который значительно более эффективен (Python? Power-Shell?) Для этоготип манипулирования файлами?

Edit2: Подробнее о том, почему я считаю это медленным.

Edit3: Часть кода, относящаяся к моему вопросу, как было запрошено в комментариях:

Public Module Public_Variables

    'Initializr technical parameters
    Public Enable_SQL_Upload As String = "Yes"
    Public Enable_CSV_Output As String = "Yes"
    Public Enable_Runlog As String = "Yes"
    Public MPF_Type As String

    'Initialize Path and Folder location
    Public Path As String '= "L:\Prophet\1902_Analysis\results\RUN_200" ' "S:\Users\Jonathan\12_Project_Space\Input" '"K:\Prophet\1809\Model_B2_LS_Analysis\results\RUN_31" 

    'Initialize parameters for Actuarial SQL database connection
    Public SQLServer As String '= "MELAIPWBAT01"
    Public SQLDataBase As String '= "VALDATA"
    Public SQLTableName As String '= "RPT_1902_" & Right(Path, 7) '"aMPF_Retail_1808"

    Public HeaderScopeFileName As String

    Public ValidFilesFileName As String = "S:\Users\Jonathan\12_Project_Space\Tables\ValidFiles.txt"
    Public InputFileName As String = "S:\Users\Jonathan\12_Project_Space\Tables\Input.txt"

    Public tsrl As String = Now.Year.ToString() + Now.Month.ToString() + Now.Day.ToString() + "_" + Now.Hour.ToString() + "h" + Now.Minute.ToString() + "m" + Now.Second.ToString() + "s"
    Public RunLogFileName As String = "\\Melaipwbat01\c$\Users\AACT064\Desktop\SQL_CSV_BULK_INSERT\RunLog" & tsrl & ".csv"
    Public RunLogFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(RunLogFileName, False)

    Public HeaderFile1 As String '= "K:\Prophet\1903\MPF\MPF_SNAPSHOT\C_TROC.rpt" ' "K:\Prophet\1903\Model_B2_LS_Analysis\results\RUN_200\C_TROC.rpt" '"K:\Prophet\1809\Model_B2_LS_Analysis\results\RUN_31\C_DIO0.rpt" 
    Public HeaderFile2 As String '= "K:\Prophet\1901\Model_GRP\results\RUN_16\CORS_0.rpt" '"K:\Prophet\1809\Model_B2_LS_Analysis\results\RUN_31\C_DIO0.rpt" 

    Public ValidFilesFile As New System.IO.StreamReader(ValidFilesFileName)


    'UserForm Design
    'Public UserFormHeight_Start As Integer = 800
    'Public UserFormWidth_Start As Integer = 800
    Public UserFormHeight_ProgressBarExtension As Integer = 0
    Public UserFormWidth_ProgressBarExtension As Integer = 0

    'Initialize Misc.
    Public Input_Array(,) As String
    Public TextLine As String
    Public TextLineSplit() As String
    Public ValidFilesArray(,) As String
    Public RecordCount As Integer = 0
    Public BodyString As String = ""
    Public SqlCommandText1 As String = ""
    Public SqlCommandText2 As String = ""

    'Initialize IS variables
    Public Is_RPT_Name As Integer = 1
    Public Is_RPT_Type As Integer = 2
    Public Is_RPT_Valid As Integer = 3

    Public Is_Name As Integer = 1
    Public Is_Type As String = 2

    Public Is_Not_found As Integer = -1
    Public Is_RetailDCS As Integer = 0
    Public Is_GroupDCS As Integer = 1
    Public Is_MPF_Type As Integer

    Public Is_Input_Header As Integer = 1
    Public Is_Input_Path As Integer = 2
    Public Is_Input_Server As Integer = 3
    Public Is_Input_Database As Integer = 4
    Public Is_Input_TableName As Integer = 5
    Public Is_Input_HeaderFileRetailDCS As Integer = 6
    Public Is_Input_HeaderFileGroupDCS As Integer = 7

    'Initialize temp variables
    Public temp_Valid As Integer

    'Initialize the header of the SQL table that is created from that application
    Public HeaderScope(,) As String
    Public HeaderMapId(,) As String
    Public HeaderStringSQL As String = ""
    Public HeaderStringCSV As String = ""
    Public MappingFound As Boolean

    'Initialization for the files looping
    Public temp_file As Integer = 1
    Public temp_line As Integer
    Public temp_headerfile As String
    Public FileSize As Integer
    Public TimerCounter As Integer = 0

End Module

Public Class UF_UserForm

    Private Sub UF_UserForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        'Me.Height = UserFormHeight_Start
        'Me.Width = UserFormWidth_Start

        TB_Input.Text = InputFileName

        CB_SQLUpload.Text = Enable_SQL_Upload
        CB_CSVOutput.Text = Enable_CSV_Output
        CB_Runlog.Text = Enable_Runlog

        GB_Progress.Visible = False
    End Sub

    Private Sub B_Run_Click_1(sender As Object, e As EventArgs) Handles B_Run.Click

        'Disable the button, switch to 'Progress' tab
        B_Run.Enabled = False
        TabControl1.SelectedIndex = 1

        'Start the Timer
        Timer1.Interval = 1000
        TimerCounter = 0
        Timer1.Start()

        'Initilialize the parameters with the Text Box values
        TB_Server.Enabled = False
        TB_Database.Enabled = False
        TB_TableName.Enabled = False
        TB_Path.Enabled = False
        TB_FileType.Enabled = False
        CB_SQLUpload.Enabled = False
        CB_CSVOutput.Enabled = False
        CB_Runlog.Enabled = False

        Enable_SQL_Upload = CB_SQLUpload.Text
        Enable_CSV_Output = CB_CSVOutput.Text
        Enable_Runlog = CB_Runlog.Text

        'Extract the inputs from the input.txt file
        Dim temp_Input As Integer
        Dim InputFirstCol As String
        Dim InputSecCol As String
        Dim Nb_Of_Runs As Integer
        Dim EndOfLoop As Boolean

        InputFileName = TB_Input.Text
        Dim InputFile As New System.IO.StreamReader(InputFileName)

        temp_Input = 0
        EndOfLoop = False
        Do While InputFile.Peek() <> -1 And EndOfLoop = False
            TextLine = InputFile.ReadLine()
            TextLineSplit = TextLine.Split(",")
            InputFirstCol = TextLineSplit(0)

            If InputFirstCol <> "#" And InputFirstCol <> "" And InputFirstCol <> "--End--" Then
                InputSecCol = TextLineSplit(1)
            Else
                InputSecCol = ""
            End If

            If InputFirstCol = "--End--" Then
                EndOfLoop = True
            Else
                If InputFirstCol = "#" Then
                    temp_Input = temp_Input + 1
                ElseIf InputFirstCol = "HeaderScope" Then
                    ReDim Preserve Input_Array(7, temp_Input)
                    Input_Array(Is_Input_Header, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "Path" Then
                    Input_Array(Is_Input_Path, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "Server" Then
                    Input_Array(Is_Input_Server, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "Database" Then
                    Input_Array(Is_Input_Database, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "TableName" Then
                    Input_Array(Is_Input_TableName, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "HeaderFileRetailDCS" Then
                    Input_Array(Is_Input_HeaderFileRetailDCS, temp_Input) = InputSecCol
                ElseIf InputFirstCol = "HeaderFileGroupDCS" Then
                    Input_Array(Is_Input_HeaderFileGroupDCS, temp_Input) = InputSecCol
                End If
            End If
        Loop

        Nb_Of_Runs = temp_Input

        'Create an array to store the timer per run
        Dim Timer_Array(Nb_Of_Runs) As String

        'Let's start the loop for each run
        For temp_Run = 1 To Nb_Of_Runs

            'Initialize date stamp variables and create the date stamp (called ts)
            Dim now As DateTime = DateTime.Now
            Dim ts As String = now.Year.ToString() + now.Month.ToString() + now.Day.ToString() + "_" + now.Hour.ToString() + "h" + now.Minute.ToString() + "m" + now.Second.ToString() + "s"
            Dim temp_full_count As Integer = 0
            Dim File_Count As Integer = 0
            Dim temp_count As Integer = 0

            'Open the.csv file
            Dim OutputCSVFileName As String = "\\Melaipwbat01\c$\Users\AACT064\Desktop\SQL_CSV_BULK_INSERT\SQL_Upload" & ts & ".csv" ' "S:\Users\Jonathan\12_Project_Space\Output\RPT_Files" & ts & ".csv"
            Dim SQLUploadFileName As String = Replace(OutputCSVFileName, "\\Melaipwbat01\c$", "C:")
            Dim SQLQueriesFileName As String = "\\Melaipwbat01\c$\Users\AACT064\Desktop\SQL_CSV_BULK_INSERT\SQL_Queries" & ts & ".csv"

            Dim outFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(OutputCSVFileName, False)
            Dim SQLQueriesFile As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(SQLQueriesFileName, False)

            'Store the inputs from the Input_Array
            SQLServer = Input_Array(Is_Input_Server, temp_Run)
            TB_Server.Text = Input_Array(Is_Input_Server, temp_Run)

            SQLDataBase = Input_Array(Is_Input_Database, temp_Run)
            TB_Database.Text = Input_Array(Is_Input_Database, temp_Run)

            SQLTableName = Input_Array(Is_Input_TableName, temp_Run)
            TB_TableName.Text = Input_Array(Is_Input_TableName, temp_Run)

            Path = Input_Array(Is_Input_Path, temp_Run)
            TB_Path.Text = Input_Array(Is_Input_Path, temp_Run)

            HeaderScopeFileName = Input_Array(Is_Input_Header, temp_Run)
            TB_FileType.Text = Input_Array(Is_Input_Header, temp_Run)

            HeaderFile1 = Input_Array(Is_Input_HeaderFileRetailDCS, temp_Run)
            TB_HeaderRetailDCS.Text = Input_Array(Is_Input_HeaderFileRetailDCS, temp_Run)

            HeaderFile2 = Input_Array(Is_Input_HeaderFileGroupDCS, temp_Run)
            TB_HeaderGroupDCS.Text = Input_Array(Is_Input_HeaderFileGroupDCS, temp_Run)

            'Open the folder location and store all the files objetcs into files()
            Dim files() As String = IO.Directory.GetFiles(Path)

            'Open the Header scope .txt file
            Dim HeaderScopeFile As New System.IO.StreamReader(HeaderScopeFileName)

            'Initialize the variable ValidFilesArray
            temp_Valid = 1
            Do While ValidFilesFile.Peek() <> -1
                TextLine = ValidFilesFile.ReadLine()
                TextLineSplit = TextLine.Split(", ")

                ReDim Preserve ValidFilesArray(3, temp_Valid)
                ValidFilesArray(Is_RPT_Name, temp_Valid) = TextLineSplit(Is_RPT_Name - 1)
                ValidFilesArray(Is_RPT_Type, temp_Valid) = TextLineSplit(Is_RPT_Type - 1)
                ValidFilesArray(Is_RPT_Valid, temp_Valid) = TextLineSplit(Is_RPT_Valid - 1)

                temp_Valid = temp_Valid + 1
            Loop

            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Display the Progress Group Box ''''''''''''''''''''''''''''''''''''''''''''''''
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            L_ProgressPC.Text = "Initialisation"
            ProgressBar.Value = 0
            GB_Progress.Visible = True
            'Me.Height = UserFormHeight_Start + UserFormHeight_ProgressBarExtension
            'Me.Width = UserFormWidth_Start + UserFormWidth_ProgressBarExtension

            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Nb of Files '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' The goal of this piece of code aims at calculating the number of .rpt files
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

            TB_Runlog.Text = "Checking number of .rpt files..." & Environment.NewLine & TB_Runlog.Text
            For Each file As String In files
                If CheckValidRPTFile(file, False) = True Then
                    File_Count = File_Count + 1
                    L_NbOfFiles.Text = File_Count
                    L_NbOfRuns.Text = temp_Run & "/" & Nb_Of_Runs
                End If
                Application.DoEvents()
            Next
            TB_Runlog.Text = "... " & " Run number " & temp_Run & Environment.NewLine & TB_Runlog.Text
            TB_Runlog.Text = "... " & File_Count & " rpt files founds" & Environment.NewLine & TB_Runlog.Text
            TB_Runlog.Text = "---------------------------------------" & Environment.NewLine & TB_Runlog.Text

            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' The key is to define the header with the field names and the field types
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            Dim HeaderNbOfField As Integer = 0
            Do While HeaderScopeFile.Peek() <> -1

                HeaderNbOfField = HeaderNbOfField + 1

                'We split the libe into an array using the comma delimiter
                TextLine = HeaderScopeFile.ReadLine()
                TextLineSplit = TextLine.Split(", ")

                ReDim Preserve HeaderScope(2, HeaderNbOfField)
                HeaderScope(Is_Name, HeaderNbOfField) = TextLineSplit(0)
                HeaderScope(Is_Type, HeaderNbOfField) = TextLineSplit(1)

            Loop

            'That array stores the position of a given field in the file
            'It is important to initialise the array to -1
            'When further down we assign HeaderMapId, if a value remains "-1" il will mean the field was not assigned thus not found.
            'We will then assign a default value for those not found fields
            ReDim HeaderMapId(1, HeaderNbOfField)
            For temp_headermapini = 0 To HeaderNbOfField
                HeaderMapId(Is_RetailDCS, temp_headermapini) = Is_Not_found
                HeaderMapId(Is_GroupDCS, temp_headermapini) = Is_Not_found
            Next

            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Header ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' The goal of this piece of code is to populate the variable HeaderMapId
            ' HeaderMapId stores the position of each field define is HeaderScope variable
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            L_ProgressPC.Text = "Find position of each field in the flat file"

            'We use HeaderFile as the base to define the position of each field
            'The application will function properly only if every .rpt file in the folder have same header as HeaderFile

            For temp_header = 0 To 1

                'We loop through 2 different type of MPFs
                'Typicaly coming from Retail DCS and Group DCS
                If temp_header = Is_RetailDCS Then
                    temp_headerfile = HeaderFile1
                ElseIf temp_header = Is_GroupDCS Then
                    temp_headerfile = HeaderFile2
                Else
                    temp_headerfile = "" 'Error
                End If

                Dim objReaderHeader As New System.IO.StreamReader(temp_headerfile)

                'We read line by line until the end of the file
                Do While objReaderHeader.Peek() <> -1

                    TextLine = objReaderHeader.ReadLine()

                    'We only care about the header, which starts with the character "!" in prophet .rpt files
                    If Strings.Left(TextLine, 1) = "!" Then

                        Dim temp_scope As Integer
                        Dim temp_scope_id As Integer

                        'We split the line in an array delimited by comma
                        TextLineSplit = TextLine.Split(", ")

                        'We loop through the array
                        'Once a field match one of the field define in HeaderScope, we store the position of that field in HeaderMapId
                        temp_scope_id = 1
                        For Each s As String In TextLineSplit
                            For temp_scope = 1 To UBound(HeaderScope, 2)
                                If HeaderScope(Is_Name, temp_scope) = s Then
                                    HeaderMapId(temp_header, temp_scope) = temp_scope_id
                                End If
                            Next
                            temp_scope_id = temp_scope_id + 1
                        Next

                    End If
                Loop

            Next

            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Header''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            'Create the query for SQL table creation
            Dim temp_field As Integer
            For temp_field = 1 To HeaderNbOfField
                If temp_field = 1 Then
                    HeaderStringSQL = "(Prophet_Name varchar(255),"
                    HeaderStringCSV = "Prophet_Name,"
                End If
                'We replace the bracket by underscore to avoid crashes when creating the SQL table
                HeaderStringSQL = HeaderStringSQL & Replace(Replace(HeaderScope(Is_Name, temp_field), "(", "_"), ")", "_") & " " & HeaderScope(Is_Type, temp_field)
                HeaderStringCSV = HeaderStringCSV & Replace(Replace(HeaderScope(Is_Name, temp_field), "(", "_"), ")", "_")

                If temp_field <> HeaderNbOfField Then
                    HeaderStringSQL = HeaderStringSQL & ","
                    HeaderStringCSV = HeaderStringCSV & ","
                Else
                    HeaderStringSQL = HeaderStringSQL & ")"
                    HeaderStringCSV = HeaderStringCSV & ","
                End If
            Next

            If Enable_CSV_Output = "Yes" Then
                'Remove braquets and single quotes
                outFile.WriteLine(Replace(Replace(Replace(HeaderStringCSV, ")", ""), "(", ""), "'", ""))
            End If

            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Body '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' We loop through all the files and pick the information we need based on HeaderMapId
            '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

            'We loop through each file in the folder location
            For Each file As String In files

                Dim objReader As New System.IO.StreamReader(file)
                Dim fileInfo As New IO.FileInfo(file)

                'We only loop through the valid .rpt files
                If CheckValidRPTFile(file, True) = True Then

                    'Count the number of files we go through
                    temp_count = temp_count + 1

                    'Count the number of lines in the file (called FileSize)
                    'Dim objReaderLineCOunt As New System.IO.StreamReader(file)
                    'FileSize = 0
                    'Do While objReaderLineCOunt.Peek() <> -1
                    'TextLine = objReaderLineCOunt.ReadLine()
                    'FileSize = FileSize + 1
                    'Loop
                    FileSize = 1000000

                    'temp_line = 1
                    ''We loop through line by line for a given file
                    'Do While objReader.Peek() <> -1

                    Dim TextLines() As String = System.IO.File.ReadAllLines(file)
                    For Each TextLine2 In TextLines

                        'Update the Progress Bar
                        temp_full_count = temp_full_count + 1

                        If temp_full_count Mod 200 = 0 Then
                            ProgressBar.Value = Int(100 * temp_count / File_Count)
                            L_ProgressPC.Text = "Processing file " & fileInfo.Name & " " & temp_count & "/" & File_Count & " - line " & temp_line & "/" & FileSize
                            L_RecordsProcessed.Text = temp_full_count
                            Application.DoEvents()
                        End If

                        'We split the libe into an array using the comma delimiter
                        'TextLine = objReader.ReadLine()
                        TextLineSplit = TextLine2.Split(", ")

                        'Skip line that are not actual prophet records (skip header and first few lines)
                        If Strings.Left(TextLine2, 1) = "*" Then

                            'We loop through the number of field we wish to extract for the file
                            For temp_field = 1 To HeaderNbOfField

                                If temp_field = 1 Then
                                    BodyString = "('" & Strings.Left(fileInfo.Name, Len(fileInfo.Name) - 4) & "',"
                                End If

                                If MPF_Type = "RetailDCS" Then
                                    Is_MPF_Type = Is_RetailDCS
                                ElseIf MPF_Type = "GroupDCS" Then
                                    Is_MPF_Type = Is_GroupDCS
                                Else
                                    MsgBox("Is_MPF_Type value is nor recognized")
                                    End
                                End If

                                'The array HeaderMapId tells us where to pick the information from the file
                                'This assumes that each file in the folder have same header as the 'HeaderFile'
                                If HeaderMapId(Is_MPF_Type, temp_field) = Is_Not_found Then
                                    BodyString = BodyString & "98766789"
                                Else
                                    BodyString = BodyString & TextLineSplit(HeaderMapId(Is_MPF_Type, temp_field) - 1)
                                End If


                                If temp_field <> HeaderNbOfField Then
                                    BodyString = BodyString & ","
                                Else
                                    BodyString = BodyString & ")"
                                End If
                            Next

                            'We replace double quotes with single quotes
                            BodyString = Replace(BodyString, """", "'")

                            'This Line is to add records to the .csv file
                            If Enable_CSV_Output = "Yes" Then
                                'Remove braquets and single quotes
                                outFile.WriteLine(Replace(Replace(Replace(BodyString, ")", ""), "(", ""), "'", ""))
                            End If

                        End If

                        temp_line = temp_line + 1

                    Next

                    TB_Runlog.Text = "Completed: " & fileInfo.Name & Environment.NewLine & TB_Runlog.Text
                    temp_file = temp_file + 1
                End If

            Next

            outFile.Close()

            ProgressBar.Value = Int(100 * temp_count / File_Count)
            L_RecordsProcessed.Text = temp_full_count
            Application.DoEvents()

            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            '' Upload to SQL '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            ' The goal of this code is to create the SQL table
            ' And push the .csv created into the SQL table using BULK INSERT function
            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
            L_ProgressPC.Text = "Creating SQL Table"
            Application.DoEvents()

            If Enable_SQL_Upload = "Yes" Then

                'First query is to create the table
                SqlCommandText1 = "CREATE TABLE [" & SQLDataBase & "].[analysis]." & SQLTableName & "_" & ts & " " & HeaderStringSQL

                'Second query is to populate the data
                SqlCommandText2 = "BULK INSERT [" & SQLDataBase & "].[analysis]." & SQLTableName & "_" & ts & " " & " FROM '" & SQLUploadFileName & "' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' , FIRSTROW=2)"

                SQLQueriesFile.WriteLine(SqlCommandText1)
                SQLQueriesFile.WriteLine(SqlCommandText2)
                SQLQueriesFile.Close()

                Using connection As New SqlConnection("Data Source=" & SQLServer & ";Integrated Security=True;Connection Timeout=2000;Initial Catalog=" & SQLDataBase & ";")
                    connection.Open()

                    Dim command As New SqlCommand(SqlCommandText1, connection)
                    command.ExecuteNonQuery()

                    Dim command2 = New SqlCommand(SqlCommandText2, connection)
                    command2.CommandTimeout = 2000
                    command2.ExecuteNonQuery()

                    connection.Close()
                End Using

            End If

            Timer_Array(temp_Run) = L_Timer.Text

        Next 'temp_Run

        RunLogFile.Close()
        Timer1.Stop()

        L_ProgressPC.Text = "Job completed"

1 Ответ

0 голосов
/ 12 июля 2019

Один из способов ускорить вашу программу - минимизировать количество обращений к диску.Прямо сейчас вы читаете каждый файл дважды, построчно.Каждый файл, скорее всего, помещается в память.Итак, что вы можете сделать, это прочитать все строки файла в памяти, а затем обработать его строки.Это будет намного быстрее.

Что-то вроде:

'We only loop through the valid .rpt files
If CheckValidRPTFile(file, True) = True Then

    ''Count the number of files we go through
    'temp_count = temp_count + 1

    ''Count the number of lines in the file (called FileSize)
    'Dim objReaderLineCOunt As New System.IO.StreamReader(file)
    'FileSize = 0
    'Do While objReaderLineCOunt.Peek() <> -1
    '    TextLine = objReaderLineCOunt.ReadLine()
    '    FileSize = FileSize + 1
    'Loop

    'temp_line = 1
    ''We loop through line by line for a given file
    'Do While objReader.Peek() <> -1

    Dim TextLines() As String = System.IO.File.ReadAllLines(file)
    For Each TextLine In TextLines

        'We split into an array using the comma delimiter
        'TextLine = objReader.ReadLine()
        TextLineSplit = TextLine.Split(", ")

Я посмотрел ваш обновленный код.У вас есть несколько дополнительных проблем с производительностью в вашем коде.

  1. Чтение и запись в файлы общих сетевых папок не очень эффективны, особенно если к файлу много прямого и обратного доступа, потому что все идет через сеть, а не через прямой доступ к локальному диску.

  2. Вероятно, самая неэффективная часть вашей программы - это итерация по вашим 200 полям для каждой строки файлов.Скажем, у нас в среднем 5000 строк на файл, то есть 200 x 5000 x 284 = 284 миллиона итераций!

Эффективный метод доступа к общим сетевым файлам - чтение всего файла.в памяти, используя System.IO.ReadAllLines() или System.IO.File.ReadAllText(), а затем обработайте его содержимое.Аналогично, запись в сетевой файл общего доступа должна состоять из построения содержимого файла в памяти (если возможно) с использованием StringBuilder или List(Of String), а затем записи всего файла в сетевой ресурс с System.IO.File.WriteAllText() из System.IO.File.WriteAllLines.Это должен быть предпочтительный способ доступа к общим сетевым файлам для лучшей производительности.

Для второй проблемы с производительностью поля сквозного прохождения могут быть упрощены следующим образом.

Dim BodyStringBuilder As New StringBuilder("")
BodyStringBuilder.Append("('" & Strings.Left(fileInfo.Name, Len(fileInfo.Name) - 4) & "',")

If MPF_Type = "RetailDCS" Then
    Is_MPF_Type = Is_RetailDCS
ElseIf MPF_Type = "GroupDCS" Then
    Is_MPF_Type = Is_GroupDCS
Else
    MsgBox("Is_MPF_Type value is nor recognized")
    End
End If

'Skip line that are not actual prophet records (skip header and first few lines)
If Strings.Left(TextLine2, 1) = "*" Then

    'We loop through the number of field we wish to extract for the file
    For temp_field = 1 To HeaderNbOfField

        'The array HeaderMapId tells us where to pick the information from the file
        'This assumes that each file in the folder have same header as the 'HeaderFile'
        If HeaderMapId(Is_MPF_Type, temp_field) = Is_Not_found Then
            BodyStringBuilder.Append("98766789,")
        Else
            BodyStringBuilder.Append(TextLineSplit(HeaderMapId(Is_MPF_Type, temp_field) - 1) & ",")
        End If
    Next

    ' Replace last "," by ")".
    BodyStringBuilder.Remove(BodyStringBuilder.Length - 1, 1).Append(")")

    'We replace double quotes with single quotes
    BodyString = Replace(BodyString.ToString, """", "'")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...