golang基于window下实现文件遍历(效率高于filepath.Wlak)

发布时间:2023年12月25日

golang基于window下实现文件遍历(效率高于filepath.Wlak)

package main

import (
	"fmt"
	"os"
	"path"
	"path/filepath"
	"syscall"
	"time"
	"unsafe"
)

const MAX_PATH = 260

type FILETIME struct {
	dwLowDateTime  uint32
	dwHighDateTime uint32
}

type WIN32_FIND_DATAW struct {
	dwFileAttributes   uint32
	ftCreationTime     FILETIME
	ftLastAccessTime   FILETIME
	ftLastWriteTime    FILETIME
	nFileSizeHigh      uint32
	nFileSizeLow       uint32
	dwReserved0        uint32
	dwReserved1        uint32
	cFileName          [MAX_PATH]uint16
	cAlternateFileName [14]uint16
	dwFileType         uint32
	dwCreatorType      uint32
	wFinderFlags       uint16
	FileName           string
}
type IndexEntry2 struct {
	Name string
	Path string
	Size uint64
}

var (
	kernel32           = syscall.NewLazyDLL("Kernel32.dll")
	procFindFirstFileW = kernel32.NewProc("FindFirstFileW")
	procFindNextFileW  = kernel32.NewProc("FindNextFileW")
	procFindClose      = kernel32.NewProc("FindClose")
)

type HANDLE uintptr

const (
	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_DATAW
	globalPath := 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 path
	dir := `E:\`

	fmt.Println(len(FindFileWin(dir)))
	// fmt.Println(len(FileWalk(dir)))
	fmt.Printf("共花费时间 %.3f seconds\n", time.Since(startTime).Seconds())
}

在这里插入图片描述

文章来源:https://blog.csdn.net/a1309525802/article/details/135195865
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。