web实现本地电脑树形目录、读取本地文件夹、输出文件内容、动态绑定事件、文件句柄、递归、showDirectoryPicker、entries、getFile、createElement


前言

目前支持.txt.html.JavaScript.css等代码文件的读取,不支持图片或文档类型的读取。


效果图

folderHandle2


html

<div class="p_20 bs_bb">
	<div class="d_f jc_c">
		<button id="idFolder" class="w_50_ fs_30 cursor_pointer">打开文件夹</button>
	</div>
	
	<div id="idContent" class="m_t_20 bs_bb p_20 bc_rgba_192_1"></div>
</div>

JavaScript

// 全局文件句柄
// 多处用到此变量
// 所以定义到全局
let root = [];

// 打开文件夹(导入文件夹)
idFolder.onclick = async function () {
	try {
		let handle = await showDirectoryPicker(),
			node = document.querySelector('#idContent');
		
		node.innerHTML = '';
		
		root = await processHandle(handle);
		
		createTreeDirectory(node, root.children);
	} catch (error) {
		console.log(error);
		// 用户拒绝的处理
	}
};

// 进程句柄(获取文件夹中的文件夹句柄和文件句柄)
async function processHandle(handle) {
	if (handle.kind === 'file') return handle;
	
	// 注意这个地方
	// 不可以定义新变量接收数据
	// 否则文件夹句柄将不能保存
	handle.children = [];
	// 得到异步迭代器
	let iter = handle.entries();
	
	for await (let item of iter) handle.children.push(await processHandle(item[1]));
	
	return handle;
}

// 通过递归创建树形目录
function createTreeDirectory(node, data) {
	const ul = document.createElement("ul");
	
	ul.className = "p_l_20";
	node.appendChild(ul);
	
	data.forEach((item) => {
		let li = document.createElement("li");
		
		li.className = item.kind === 'file' ? 'fs_18 w_fc cursor_pointer' : '';
		// 动态绑定事件
		if (item.kind === 'file') li.onclick = handleFileContent;
		
		ul.appendChild(li);
		
		if (item.children && item.children.length > 0) {
			const details = document.createElement("details");
			
			li.appendChild(details);
			
			const summary = document.createElement("summary");
			
			summary.className = item.kind === 'directory' ? "fs_18 w_fc cursor_default" : "";
			summary.textContent = item.name;
			details.appendChild(summary);
			
			createTreeDirectory(details, item.children);
		} else {
			li.textContent = item.name;
		}
	});
}

// 文件点击事件
function handleFileContent({ target: { innerText } }) {
	getFileHandle(root.children, innerText);
}

// 通过递归获取指定文件句柄
function getFileHandle(data, name) {
	for (let i = 0; i < data.length; i++) {
		let item = data[i];
		
		if (item.name === name) {
			return readText(item);
		} else {
			if (item.children && item.children.length > 0) {
				let res = getFileHandle(item.children, name);
				
				if (res) return res;
			}
		}
	}
}

// 输出文件内容
async function readText(fileHandle) {
	let file = await fileHandle.getFile(),
		reader = new FileReader();
	
	reader.onload = ({ target: { result } }) => {
		console.log(`-------输出结果-------\n${result}`);
	}
	
	reader.readAsText(file, 'utf-8');
}
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
实现这个功能,你需要使用 Windows API 来监控文件系统的变化。具体步骤如下: 1. 使用 FindFirstChangeNotification 函数创建一个句柄,用于监控目录的变化。 2. 使用 ReadDirectoryChangesW 函数读取变化的信息,可以得到新生成的文件名。 3. 使用 CreateFile 函数打开该文件,并读取文件内容。 4. 打印文件内容。 以下是示例代码: ```c #include <stdio.h> #include <windows.h> void monitorDirectoryChanges(const char* path) { HANDLE dirHandle = FindFirstChangeNotification(path, FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE); if (dirHandle == INVALID_HANDLE_VALUE) { printf("Failed to monitor directory changes\n"); return; } while (TRUE) { if (FindNextChangeNotification(dirHandle) == FALSE) { printf("Failed to find next change notification\n"); break; } DWORD bytesReturned = 0; char buffer[1024]; if (ReadDirectoryChangesW(dirHandle, buffer, sizeof(buffer), TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &bytesReturned, NULL, NULL) == FALSE) { printf("Failed to read directory changes\n"); break; } PFILE_NOTIFY_INFORMATION fileInfo = (PFILE_NOTIFY_INFORMATION) buffer; while (fileInfo != NULL) { // Get the file name WCHAR fileName[1024]; memcpy(fileName, fileInfo->FileName, fileInfo->FileNameLength); fileName[fileInfo->FileNameLength / 2] = L'\0'; // Open the file and read its contents char filePath[1024]; sprintf(filePath, "%s\\%S", path, fileName); HANDLE fileHandle = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { printf("Failed to open file %s\n", filePath); } else { DWORD fileSize = GetFileSize(fileHandle, NULL); char* fileContents = (char*) malloc(fileSize + 1); if (fileContents == NULL) { printf("Failed to allocate memory for file contents\n"); } else { if (ReadFile(fileHandle, fileContents, fileSize, NULL, NULL) == FALSE) { printf("Failed to read file %s\n", filePath); } else { fileContents[fileSize] = '\0'; printf("File contents of %s:\n%s\n", filePath, fileContents); } free(fileContents); } CloseHandle(fileHandle); } fileInfo = fileInfo->NextEntryOffset != 0 ? (PFILE_NOTIFY_INFORMATION) ((LPBYTE) fileInfo + fileInfo->NextEntryOffset) : NULL; } } FindCloseChangeNotification(dirHandle); } int main() { monitorDirectoryChanges("C:\\test"); return 0; } ``` 注意,这里只监控了目录下最后写入的文件变化,如果需要监控其他类型的变化,需要修改 `FILE_NOTIFY_CHANGE_LAST_WRITE` 参数。同时,由于是在 Windows 平台下实现的,所以代码中使用了 Windows API。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值