VB 대용량 Text파일을 빠른속도로 읽어 들이기
페이지 정보
작성자
본문
제목처럼 거창한건 아니구요..
그냥.. VB함수 Open을 사용하여.. 한 Line씩 읽어들일때와
API ReadFile을 사용하여... 파일을 읽어 들일때의 속도를 비교해 보았습니다..
첨부한 파일은 약 1메가가 조금 넘는 Text파일(TestData.txt)이라..
그리 큰 차이는 없지만.. 수백메가의 파일을 읽을때에는 차이가 납니다..
API로 파일을 읽어서 사용할때에는
파일읽는 속도는 정말 빠릅니다...
그러나 문제는... 읽은 데이터값이.. Byte 배열로 들어간다는것이 문제더군요..
이것을 String으로 변환하기 위해서.. 함수를 만들었는데..
바이트 배열을 String으로 변환하는데 상당히 많은 시간이 소요되는데.
그래도... 두개를 비교하면.. 조금 더 빠릅니다...
필요할때마다... String을 변환해서.. 사용하시면.. 무지 빠를거라고 생각합니다..
실전에서 사용하시기에는 조금 손을 보셔야 할겁니다...
필요하신 분들은 참고해보세요.. ^^*
[Module]
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function Get_DataString(abt() As Byte, n_start As Long, n_Len As Long)
'바이트 배열 String 변환을 위한 함수
'Original 바이트 배열 주소에 있는 Data를 임시 배열에 집어넣는다.
'CopyMemory 사용
On Error Resume Next
Dim lcnt As Long
Dim sTarget() As Byte
ReDim sTarget(n_start To n_start + n_Len) As Byte
CopyMemory ByVal VarPtr(sTarget(n_start)), ByVal VarPtr(abt(n_start)), (UBound(sTarget) - LBound(sTarget)) * LenB(sTarget(n_start))
Get_DataString = ByteArrayToString(sTarget)
End Function
Public Function ByteArrayToString(RcvArray() As Byte) As String
Dim sRtnString As String
Dim lcnt As Long
Dim rtnbyte() As Byte
'바이트 배열을 vbUnicode Convert하여 넘긴다.
'1042 -> LocailID 대한민국:1042 -> MSDN참조
sRtnString = ""
ByteArrayToString = Trim(StrConv(RcvArray, vbUnicode, 1042))
End Function
[Form ]
Option Explicit
Dim bBytes() As Byte
Const RFileName = "\TestData.txt"
Const MOVEFILE_REPLACE_EXISTING = &H1
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_BEGIN = 0
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Sub CmdApiStart_Click()
'Api 함수를 이용하여 File을 읽는다.
'파일 내용은 Byte 배열로 들어가기 때문에...
'String으로 반환하기 위해서는 Byte 배열내의 Data를 String으로 Convert하는
'과정이 필요함
Dim lngFileHandle As Long
Dim lngFileSize As Long
Dim lngRet As Long
Dim lngLoop As Long
Dim strTemp As String
Dim sngStart As Single
Dim sngStop As Single
Dim sngDuration As Single
TxtALineStatus = "파일 읽기 시작"
sngStart = Timer
TxtAOpen = CStr(sngStart): TxtAOpen.Refresh
'파일 핸들값을 얻어온다.
lngFileHandle = CreateFile(App.Path & RFileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
'파일의 사이즈를 얻어온다. -> 사이즈 만큼 바이트배열 할당을 위하여
lngFileSize = GetFileSize(lngFileHandle, 0)
'파일 포인터를 설정한다.
SetFilePointer lngFileHandle, 0, 0, FILE_BEGIN
'바이트 배열의 크기를 파일 사이즈 만큼 잡는다
ReDim bBytes(1 To CLng(lngFileSize)) As Byte
'파일을 읽어 바이트 배열로 넣는다
ReadFile lngFileHandle, bBytes(1), UBound(bBytes), lngRet, ByVal 0&
'파일읽기 완료
'바이트 배열을 String으로 변환한다.
'1024 바이트씩 읽어 들인다.
For lngLoop = 1 To UBound(bBytes) Step 1024
strTemp = Get_DataString(bBytes, lngLoop, 1024)
'CRLF 처리를 하여.. 한 라인씩 변수에 넣으면 된다. split 함수 사용
DoEvents
Next lngLoop
'바이트 배열을 지운다.
ReDim bBytes(0) As Byte
'파일을 닫는다.
CloseHandle lngFileHandle
sngStop = Timer
TxtAStop = CStr(sngStop): TxtAStop.Refresh
TxtALineStatus = "파일 오픈 종료"
TxtADuration = sngStop - sngStart
TxtADuration.Refresh
MsgBox "파일의 마지막 Line : " & strTemp
End Sub
Private Sub CmdLineStart_Click()
'Open 함수를 이용 Text File을 Open 한 뒤 읽어들인다.
Dim LF As Long 'File Pointer
Dim strLine As String '파일을 한 라인씩 읽어들이는 변수
Dim sngStart As Single
Dim sngStop As Single
Dim sngDuration As Single
TxtLineStatus = "파일 읽기 시작"
sngStart = Timer
TxtOpen = CStr(sngStart): TxtOpen.Refresh
LF = FreeFile()
Open App.Path & RFileName For Input As LF '파일 Open 읽기
Do While Not EOF(LF)
Line Input #LF, strLine '내용을 읽어들인다.
DoEvents
Loop
Close #LF
sngStop = Timer
TxtStop = CStr(sngStop): TxtStop.Refresh
TxtLineStatus = "파일 오픈 종료"
TxtDuration = sngStop - sngStart
TxtDuration.Refresh
MsgBox "파일의 마지막 Line : " & strLine
End Sub
출처 : http://cafe.daum.net/kimjongok [이 게시물은 오원장님에 의해 2013-02-28 16:41:58 오피스팁에서 이동 됨]
그냥.. VB함수 Open을 사용하여.. 한 Line씩 읽어들일때와
API ReadFile을 사용하여... 파일을 읽어 들일때의 속도를 비교해 보았습니다..
첨부한 파일은 약 1메가가 조금 넘는 Text파일(TestData.txt)이라..
그리 큰 차이는 없지만.. 수백메가의 파일을 읽을때에는 차이가 납니다..
API로 파일을 읽어서 사용할때에는
파일읽는 속도는 정말 빠릅니다...
그러나 문제는... 읽은 데이터값이.. Byte 배열로 들어간다는것이 문제더군요..
이것을 String으로 변환하기 위해서.. 함수를 만들었는데..
바이트 배열을 String으로 변환하는데 상당히 많은 시간이 소요되는데.
그래도... 두개를 비교하면.. 조금 더 빠릅니다...
필요할때마다... String을 변환해서.. 사용하시면.. 무지 빠를거라고 생각합니다..
실전에서 사용하시기에는 조금 손을 보셔야 할겁니다...
필요하신 분들은 참고해보세요.. ^^*
[Module]
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Public Function Get_DataString(abt() As Byte, n_start As Long, n_Len As Long)
'바이트 배열 String 변환을 위한 함수
'Original 바이트 배열 주소에 있는 Data를 임시 배열에 집어넣는다.
'CopyMemory 사용
On Error Resume Next
Dim lcnt As Long
Dim sTarget() As Byte
ReDim sTarget(n_start To n_start + n_Len) As Byte
CopyMemory ByVal VarPtr(sTarget(n_start)), ByVal VarPtr(abt(n_start)), (UBound(sTarget) - LBound(sTarget)) * LenB(sTarget(n_start))
Get_DataString = ByteArrayToString(sTarget)
End Function
Public Function ByteArrayToString(RcvArray() As Byte) As String
Dim sRtnString As String
Dim lcnt As Long
Dim rtnbyte() As Byte
'바이트 배열을 vbUnicode Convert하여 넘긴다.
'1042 -> LocailID 대한민국:1042 -> MSDN참조
sRtnString = ""
ByteArrayToString = Trim(StrConv(RcvArray, vbUnicode, 1042))
End Function
[Form ]
Option Explicit
Dim bBytes() As Byte
Const RFileName = "\TestData.txt"
Const MOVEFILE_REPLACE_EXISTING = &H1
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_BEGIN = 0
Const FILE_SHARE_READ = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW = 1
Const OPEN_EXISTING = 3
Const GENERIC_READ = &H80000000
Const GENERIC_WRITE = &H40000000
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hFile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hFile As Long, lpFileSizeHigh As Long) As Long
Private Sub CmdApiStart_Click()
'Api 함수를 이용하여 File을 읽는다.
'파일 내용은 Byte 배열로 들어가기 때문에...
'String으로 반환하기 위해서는 Byte 배열내의 Data를 String으로 Convert하는
'과정이 필요함
Dim lngFileHandle As Long
Dim lngFileSize As Long
Dim lngRet As Long
Dim lngLoop As Long
Dim strTemp As String
Dim sngStart As Single
Dim sngStop As Single
Dim sngDuration As Single
TxtALineStatus = "파일 읽기 시작"
sngStart = Timer
TxtAOpen = CStr(sngStart): TxtAOpen.Refresh
'파일 핸들값을 얻어온다.
lngFileHandle = CreateFile(App.Path & RFileName, GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, 0, 0)
'파일의 사이즈를 얻어온다. -> 사이즈 만큼 바이트배열 할당을 위하여
lngFileSize = GetFileSize(lngFileHandle, 0)
'파일 포인터를 설정한다.
SetFilePointer lngFileHandle, 0, 0, FILE_BEGIN
'바이트 배열의 크기를 파일 사이즈 만큼 잡는다
ReDim bBytes(1 To CLng(lngFileSize)) As Byte
'파일을 읽어 바이트 배열로 넣는다
ReadFile lngFileHandle, bBytes(1), UBound(bBytes), lngRet, ByVal 0&
'파일읽기 완료
'바이트 배열을 String으로 변환한다.
'1024 바이트씩 읽어 들인다.
For lngLoop = 1 To UBound(bBytes) Step 1024
strTemp = Get_DataString(bBytes, lngLoop, 1024)
'CRLF 처리를 하여.. 한 라인씩 변수에 넣으면 된다. split 함수 사용
DoEvents
Next lngLoop
'바이트 배열을 지운다.
ReDim bBytes(0) As Byte
'파일을 닫는다.
CloseHandle lngFileHandle
sngStop = Timer
TxtAStop = CStr(sngStop): TxtAStop.Refresh
TxtALineStatus = "파일 오픈 종료"
TxtADuration = sngStop - sngStart
TxtADuration.Refresh
MsgBox "파일의 마지막 Line : " & strTemp
End Sub
Private Sub CmdLineStart_Click()
'Open 함수를 이용 Text File을 Open 한 뒤 읽어들인다.
Dim LF As Long 'File Pointer
Dim strLine As String '파일을 한 라인씩 읽어들이는 변수
Dim sngStart As Single
Dim sngStop As Single
Dim sngDuration As Single
TxtLineStatus = "파일 읽기 시작"
sngStart = Timer
TxtOpen = CStr(sngStart): TxtOpen.Refresh
LF = FreeFile()
Open App.Path & RFileName For Input As LF '파일 Open 읽기
Do While Not EOF(LF)
Line Input #LF, strLine '내용을 읽어들인다.
DoEvents
Loop
Close #LF
sngStop = Timer
TxtStop = CStr(sngStop): TxtStop.Refresh
TxtLineStatus = "파일 오픈 종료"
TxtDuration = sngStop - sngStart
TxtDuration.Refresh
MsgBox "파일의 마지막 Line : " & strLine
End Sub
출처 : http://cafe.daum.net/kimjongok [이 게시물은 오원장님에 의해 2013-02-28 16:41:58 오피스팁에서 이동 됨]
댓글목록
등록된 댓글이 없습니다.