7 changed files with 123 additions and 6 deletions
@ -0,0 +1,93 @@ |
|||||||
|
import 'dart:io'; |
||||||
|
import 'dart:collection'; |
||||||
|
|
||||||
|
Future<Map<String, int>> searchInFiles({ |
||||||
|
required String folderPath, |
||||||
|
required String filePattern, |
||||||
|
required List<String> searchTerms, |
||||||
|
required bool caseSensitive, |
||||||
|
required bool wholeWord, |
||||||
|
}) async { |
||||||
|
// 初始化结果映射,默认所有搜索词出现0次 |
||||||
|
final result = HashMap<String, int>( |
||||||
|
equals: caseSensitive ? null : (a, b) => a.toLowerCase() == b.toLowerCase(), |
||||||
|
hashCode: caseSensitive ? null : (s) => s.toLowerCase().hashCode, |
||||||
|
); |
||||||
|
|
||||||
|
for (final term in searchTerms) { |
||||||
|
result[term] = 0; |
||||||
|
} |
||||||
|
|
||||||
|
// 获取文件夹下所有匹配的文件 |
||||||
|
final dir = Directory(folderPath); |
||||||
|
if (!await dir.exists()) { |
||||||
|
throw ArgumentError('Directory does not exist: $folderPath'); |
||||||
|
} |
||||||
|
|
||||||
|
final files = await dir.list() |
||||||
|
.where((entity) => entity is File) |
||||||
|
.cast<File>() |
||||||
|
.where((file) => _matchesPattern(file.path, filePattern)) |
||||||
|
.toList(); |
||||||
|
|
||||||
|
// 为每个搜索词构建正则表达式 |
||||||
|
final regexMap = <String, RegExp>{}; |
||||||
|
for (final term in searchTerms) { |
||||||
|
final pattern = wholeWord |
||||||
|
? r'(?<!\w)' + RegExp.escape(term) + r'(?!\w)' |
||||||
|
: term; |
||||||
|
|
||||||
|
regexMap[term] = RegExp( |
||||||
|
pattern, |
||||||
|
caseSensitive: caseSensitive, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
// 并行处理文件 |
||||||
|
await Future.wait(files.map((file) async { |
||||||
|
try { |
||||||
|
final content = await file.readAsString(); |
||||||
|
|
||||||
|
for (final term in searchTerms) { |
||||||
|
final regex = regexMap[term]!; |
||||||
|
final matches = regex.allMatches(content); |
||||||
|
result[term] = result[term]! + matches.length; |
||||||
|
} |
||||||
|
} catch (e) { |
||||||
|
print('Error reading file ${file.path}: $e'); |
||||||
|
} |
||||||
|
})); |
||||||
|
|
||||||
|
// 移除匹配次数为0的项 |
||||||
|
result.removeWhere((_, count) => count == 0); |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool _matchesPattern(String fileName, String pattern) { |
||||||
|
// 简单的通配符匹配实现(支持 *.txt 这样的简单模式) |
||||||
|
if (pattern == '*') return true; |
||||||
|
if (pattern.startsWith('*.')) { |
||||||
|
final ext = pattern.substring(1); |
||||||
|
return fileName.toLowerCase().endsWith(ext.toLowerCase()); |
||||||
|
} |
||||||
|
// 更复杂的模式可以在这里扩展 |
||||||
|
return RegExp(pattern.replaceAll('.', r'\.').replaceAll('*', '.*'), |
||||||
|
caseSensitive: false).hasMatch(fileName); |
||||||
|
} |
||||||
|
|
||||||
|
// 使用示例 |
||||||
|
void main() async { |
||||||
|
final result = await searchInFiles( |
||||||
|
folderPath: '/path/to/your/folder', |
||||||
|
filePattern: '*.txt', // 或者 '*.dart' 等 |
||||||
|
searchTerms: ['Flutter', 'Dart', 'widget', 'main'], |
||||||
|
caseSensitive: false, |
||||||
|
wholeWord: true, |
||||||
|
); |
||||||
|
|
||||||
|
print('Search results:'); |
||||||
|
result.forEach((term, count) { |
||||||
|
print('$term: $count'); |
||||||
|
}); |
||||||
|
} |
Loading…
Reference in new issue