golang基于window下实现文件遍历(效率高于filepath.Wlak)
package mainimport ("fmt""os""path""path/filepath""syscall""time""unsafe"
)const MAX_PATH = 260type FILETIME struct {dwLowDateTime uint32dwHighDateTime uint32
}type WIN32_FIND_DATAW struct {dwFileAttributes uint32ftCreationTime FILETIMEftLastAccessTime FILETIMEftLastWriteTime FILETIMEnFileSizeHigh uint32nFileSizeLow uint32dwReserved0 uint32dwReserved1 uint32cFileName [MAX_PATH]uint16cAlternateFileName [14]uint16dwFileType uint32dwCreatorType uint32wFinderFlags uint16FileName string
}
type IndexEntry2 struct {Name stringPath stringSize uint64
}var (kernel32 = syscall.NewLazyDLL("Kernel32.dll")procFindFirstFileW = kernel32.NewProc("FindFirstFileW")procFindNextFileW = kernel32.NewProc("FindNextFileW")procFindClose = kernel32.NewProc("FindClose")
)type HANDLE uintptrconst (FILE_ATTRIBUTE_DIRECTORY = 0x10
)func FindFirstFileW(lpFileName string, lpFindFileData *WIN32_FIND_DATAW) HANDLE {name, _ := syscall.UTF16PtrFromString(lpFileName)pathPtr := uintptr(unsafe.Pointer(name))handle, _, _ := procFindFirstFileW.Call(pathPtr, uintptr(unsafe.Pointer(lpFindFileData)), 0)return HANDLE(handle)
}func FindNextFileW(hFindFile HANDLE, lpFindFileData *WIN32_FIND_DATAW) bool {ret, _, _ := procFindNextFileW.Call(uintptr(hFindFile), uintptr(unsafe.Pointer(lpFindFileData)), 0)return ret != 0
}func FindClose(hFindFile HANDLE) bool {ret, _, _ := procFindClose.Call(uintptr(hFindFile))return ret != 0
}
func FindFileWin(dir string) []IndexEntry2 {list := make([]IndexEntry2, 0)var findData WIN32_FIND_DATAWglobalPath := dir + "\\*"hFindFile := FindFirstFileW(globalPath, &findData)if hFindFile != 0 {defer FindClose(hFindFile)for {fileName := syscall.UTF16ToString(findData.cFileName[:])//文件夾if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0 {if (fileName != "..") && (fileName != ".") {subPath := path.Join(dir, fileName)list = append(list, FindFileWin(subPath)...)}} else {list = append(list, IndexEntry2{Name: fileName,Size: uint64(findData.nFileSizeLow) | (uint64(findData.nFileSizeHigh) << 32),Path: path.Join(dir, fileName),})}if !FindNextFileW(hFindFile, &findData) {break // End of search}}}return list
}
func FileWalk(dir string) []IndexEntry2 {list := make([]IndexEntry2, 0)filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {if info.IsDir() {return nil}list = append(list, IndexEntry2{Path: path,Size: uint64(info.Size()),Name: info.Name(),})return nil})return list
}func main() {startTime := time.Now()// Replace the path with the desired directory pathdir := `E:\`fmt.Println(len(FindFileWin(dir)))// fmt.Println(len(FileWalk(dir)))fmt.Printf("共花费时间 %.3f seconds\n", time.Since(startTime).Seconds())
}
