欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Python開發(fā)高效文件搜索與內容匹配工具

 更新時間:2025年03月31日 10:30:14   作者:探客白澤  
在日常的開發(fā)和辦公中,查找和篩選特定文件或文件內容的需求十分常見,本文將基于PyQt6開發(fā)一個文件搜索工具,有需要的小伙伴可以參考一下

在日常的開發(fā)和辦公中,查找和篩選特定文件或文件內容的需求十分常見。尤其是在處理大量文件時,如何高效地搜索到所需內容,往往是一個挑戰(zhàn)。今天,我們將分享一個基于PyQt6的文件搜索工具,它不僅能根據(jù)文件后綴進行搜索,還支持關鍵字匹配和詳細信息展示。通過這款工具,您可以更高效地管理和查找文件,提升工作效率。

1.概述

這款基于PyQt6開發(fā)的文件搜索工具,具備文件搜索、文件內容匹配、搜索結果顯示及導出功能。程序支持通過拖拽輸入框選擇目標文件夾,并對其中的文件進行后綴篩選和內容搜索。匹配結果可以實時顯示在界面上,用戶可以查看匹配的文件名、大小以及路徑,還可以導出搜索結果或者樹結構信息。

該工具的核心特點包括:

  • 多線程搜索:使用PyQt的QThread進行文件搜索操作,避免UI卡頓。
  • 多種文件編碼支持:支持UTF-8、GBK等常見編碼格式,能夠準確讀取文件內容。
  • 實時展示匹配結果:搜索結果實時更新,方便用戶查看和處理。
  • 導入導出功能:支持導入文件樹信息及導出搜索結果。

2.功能使用

2.1 文件夾選擇與搜索設置

啟動應用后,用戶首先需要選擇一個目標文件夾,輸入需要搜索的文件后綴以及關鍵詞。文件后綴支持通過分號分隔的多項選擇,例如 .txt; .log,而關鍵詞則是搜索文件內容時所需要匹配的字符串。

界面上設計了拖拽功能,用戶可以直接將目標文件夾拖拽到輸入框中,免去手動輸入路徑的麻煩。

2.2 文件內容搜索

輸入完搜索條件后,點擊“開始搜索”按鈕,程序會啟動一個后臺線程(SearchWorker),在目標文件夾中遞歸查找符合條件的文件。搜索的內容不僅是文件名匹配,還包括文件內部的內容是否包含指定的關鍵字。程序采用了多種編碼方式進行文件內容的讀取,以確保文件格式不同的情況下能夠正確處理。

搜索過程中,UI界面并不會卡頓,用戶可以繼續(xù)操作其他功能。匹配到的文件會實時顯示在左側的文件樹結構中,每一項顯示文件名、大小和路徑等信息。

2.3 單文件搜索

除了支持批量文件搜索外,程序還提供了單文件搜索的功能。在“單文件搜索”板塊中,用戶可以選擇指定的文件,輸入要查找的關鍵詞,點擊搜索按鈕后,程序會展示匹配到的行及其內容,并在右側的文本框中顯示完整匹配結果。

該功能可以幫助開發(fā)人員快速定位特定代碼段或文件中的問題,極大提高了工作效率。

2.4 結果展示與導出

搜索結束后,程序會統(tǒng)計文件總數(shù)、匹配的行數(shù)和搜索所花費的時間,展示在界面上。同時,所有匹配到的結果會以列表的形式顯示在右側,用戶可以選擇具體的行進行查看。

如果用戶需要保存搜索結果,程序提供了導出功能。用戶可以將所有匹配的文件內容導出為文本文件,方便后續(xù)查看或共享。另外,文件樹的結構信息也可以導出,便于存檔和分析。

2.5 文件樹信息導入

程序還支持導入文件樹信息。用戶可以將之前導出的樹結構文件導入到工具中,快速恢復之前的搜索狀態(tài)和文件結構。導入后的文件樹可以繼續(xù)進行搜索或查看,提升了工具的靈活性和可用性。

3.代碼結構與實現(xiàn)

3.1 多線程處理

為了保證UI界面的流暢性,程序使用了PyQt的QThread來處理搜索任務。具體來說,SearchWorker類負責遍歷目標文件夾并查找符合條件的文件,而FileReader類則負責讀取文件內容并檢查是否包含指定的關鍵字。多線程的使用有效避免了UI在進行文件搜索時的卡頓問題,讓用戶能夠在后臺進行其他操作。

class SearchWorker(QThread):
    update_file = pyqtSignal(dict)
    finished = pyqtSignal()

    def __init__(self, folder, extensions, keyword):
        super().__init__()
        self.folder = folder
        self.extensions = extensions
        self.keyword = keyword

    def run(self):
        # 搜索文件并匹配關鍵字
        pass

3.2 文件編碼支持

文件內容的讀取采用了多種常見編碼格式(如UTF-8、GBK等),以確保無論文件是用哪種編碼保存,程序都能正確地讀取其內容。在FileReader類中,我們嘗試了不同的編碼方式,直到成功讀取文件為止。

def file_contains_keyword(self, path, keyword):
for encoding in [‘utf-8’, ‘gbk’, ‘latin-1’]:
try:
with open(path, ‘r’, encoding=encoding) as f:
return any(keyword in line for line in f)
except (UnicodeDecodeError, Exception):
continue
return False

3.3 導入導出功能

導出功能實現(xiàn)了將文件匹配結果和文件樹結構導出為文本文件,支持用戶將數(shù)據(jù)保存在指定路徑。通過QFileDialog對話框,用戶可以選擇保存的位置或導入的數(shù)據(jù)文件。

def export_match_list(self):
    # 導出匹配結果
    pass

def import_tree_info(self):
    # 導入文件樹
    pass

4.效果展示

5.相關源碼

import sys
import os
import time
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
    QLabel, QLineEdit, QPushButton, QTreeWidget, QTreeWidgetItem,
    QListWidget, QTextEdit, QScrollArea, QFileDialog, QMessageBox
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QMimeData, QSize
from PyQt6.QtGui import QDragEnterEvent, QDropEvent
 
class DraggableLineEdit(QLineEdit):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setAcceptDrops(True)
 
    def dragEnterEvent(self, event: QDragEnterEvent):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
 
    def dropEvent(self, event: QDropEvent):
        urls = event.mimeData().urls()
        if urls:
            path = urls[0].toLocalFile()
            if os.path.isdir(path) or os.path.isfile(path):
                self.setText(path)
 
class SearchWorker(QThread):
    update_file = pyqtSignal(dict)
    finished = pyqtSignal()
     
    def __init__(self, folder, extensions, keyword):
        super().__init__()
        self.folder = folder
        self.extensions = extensions
        self.keyword = keyword
        self.running = True
 
    def run(self):
        for root, _, files in os.walk(self.folder):
            if not self.running: break
            for file in files:
                if any(file.endswith(ext) for ext in self.extensions):
                    path = os.path.join(root, file)
                    if self.file_contains_keyword(path, self.keyword):
                        size = os.path.getsize(path)
                        self.update_file.emit({
                            "name": file,
                            "size": self.format_size(size),
                            "path": path
                        })
        self.finished.emit()
 
    def file_contains_keyword(self, path, keyword):
        for encoding in ['utf-8', 'gbk', 'latin-1']:
            try:
                with open(path, 'r', encoding=encoding) as f:
                    return any(keyword in line for line in f)
            except (UnicodeDecodeError, Exception):
                continue
        return False
 
    def format_size(self, size):
        if size < 1024:
            return f"{size} B"
        elif size < 1024 * 1024:
            return f"{size/1024:.1f} KB"
        else:
            return f"{size/(1024 * 1024):.1f} MB"
 
class FileReader(QThread):
    update_line = pyqtSignal(str)
    finished = pyqtSignal()
     
    def __init__(self, path, keyword):
        super().__init__()
        self.path = path
        self.keyword = keyword
        self.results = []
 
    def run(self):
        self.results = []
        for encoding in ['utf-8', 'gbk', 'latin-1']:
            try:
                with open(self.path, 'r', encoding=encoding) as f:
                    for i, line in enumerate(f, 1):
                        if self.keyword in line:
                            text = f"Line {i}: {line.strip()[:50]}"
                            self.update_line.emit(text)
                            self.results.append(line.strip())
                break
            except (UnicodeDecodeError, Exception):
                continue
        self.finished.emit()
 
class AllFilesReader(QThread):
    update_line = pyqtSignal(str)
    finished = pyqtSignal()
     
    def __init__(self, paths, keyword):
        super().__init__()
        self.paths = paths
        self.keyword = keyword
 
    def run(self):
        for path in self.paths:
            if not os.path.isfile(path):
                continue
            reader = FileReader(path, self.keyword)
            reader.update_line.connect(self.update_line.emit)
            reader.start()
            reader.wait()
        self.finished.emit()
 
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.current_matches = []
        self.search_thread = None
        self.file_reader = None
        self.start_time = 0
        self.init_ui()
 
    def init_ui(self):
        self.setWindowTitle("PyQt6文件搜索工具")
        self.setGeometry(100, 100, 1200, 700)
 
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout(main_widget)
 
        # 頂部控制面板
        top_panel = QWidget()
        top_layout = QGridLayout(top_panel)
         
        self.folder_input = DraggableLineEdit()
        self.ext_input = QLineEdit(".txt")
        self.keyword_input = QLineEdit()
        self.btn_search = QPushButton("開始搜索")
        self.btn_search.clicked.connect(self.start_search)
 
        top_layout.addWidget(QLabel("目標文件夾:"), 0, 0)
        top_layout.addWidget(self.folder_input, 0, 1)
        top_layout.addWidget(self.create_browse_btn(), 0, 2)
        top_layout.addWidget(QLabel("文件后綴:"), 1, 0)
        top_layout.addWidget(self.ext_input, 1, 1)
        top_layout.addWidget(QLabel("搜索內容:"), 2, 0)
        top_layout.addWidget(self.keyword_input, 2, 1)
        top_layout.addWidget(self.btn_search, 0, 3, 3, 1)
 
        # 統(tǒng)計信息
        stats_panel = QWidget()
        stats_layout = QHBoxLayout(stats_panel)
        self.file_count = QLabel("文件總數(shù): 0")
        self.line_count = QLabel("匹配行數(shù): 0")
        self.time_label = QLabel("耗時: 0.00秒")
        stats_layout.addWidget(self.file_count)
        stats_layout.addWidget(self.line_count)
        stats_layout.addWidget(self.time_label)
 
        # 主內容區(qū)域
        content_panel = QWidget()
        content_layout = QHBoxLayout(content_panel)
 
        # 左側結果樹
        self.tree = QTreeWidget()
        self.tree.setHeaderLabels(["文件名", "大小", "路徑"])
        self.tree.setColumnWidth(0, 250)
        self.tree.setColumnWidth(1, 100)
        self.tree.doubleClicked.connect(self.on_tree_double_click)
        tree_scroll = QScrollArea()
        tree_scroll.setWidgetResizable(True)
        tree_scroll.setWidget(self.tree)
 
        # 右側面板
        right_panel = QWidget()
        right_layout = QVBoxLayout(right_panel)
 
        # 按鈕面板
        btn_panel = QWidget()
        btn_layout = QHBoxLayout(btn_panel)
        self.btn_search_all = QPushButton("搜索所有文件")
        self.btn_export_matches = QPushButton("導出結果")
        self.btn_export_tree = QPushButton("導出樹信息")
        self.btn_import_tree = QPushButton("導入樹信息")
        btn_layout.addWidget(self.btn_search_all)
        btn_layout.addWidget(self.btn_export_matches)
        btn_layout.addWidget(self.btn_export_tree)
        btn_layout.addWidget(self.btn_import_tree)
 
        # 單文件搜索
        single_panel = QWidget()
        single_layout = QHBoxLayout(single_panel)
        self.single_input = DraggableLineEdit()
        btn_single = QPushButton("搜索")
        btn_single.clicked.connect(self.single_file_search)
        single_layout.addWidget(QLabel("單文件搜索:"))
        single_layout.addWidget(self.single_input)
        single_layout.addWidget(btn_single)
 
        # 匹配列表
        self.match_list = QListWidget()
        self.match_list.doubleClicked.connect(self.on_list_double_click)
        list_scroll = QScrollArea()
        list_scroll.setWidgetResizable(True)
        list_scroll.setWidget(self.match_list)
 
        # 詳情文本框
        self.detail_text = QTextEdit()
        self.detail_text.setReadOnly(True)
 
        right_layout.addWidget(single_panel)
        right_layout.addWidget(btn_panel)
        right_layout.addWidget(list_scroll)
        right_layout.addWidget(self.detail_text)
 
        content_layout.addWidget(tree_scroll)
        content_layout.addWidget(right_panel)
 
        main_layout.addWidget(top_panel)
        main_layout.addWidget(stats_panel)
        main_layout.addWidget(content_panel)
 
        # 連接新按鈕信號
        self.btn_search_all.clicked.connect(self.search_all_files)
        self.btn_export_matches.clicked.connect(self.export_match_list)
        self.btn_export_tree.clicked.connect(self.export_tree_info)
        self.btn_import_tree.clicked.connect(self.import_tree_info)
 
    def create_browse_btn(self):
        btn = QPushButton("瀏覽")
        btn.clicked.connect(self.browse_folder)
        btn.setFixedSize(QSize(80, 30))
        return btn
 
    def browse_folder(self):
        path = QFileDialog.getExistingDirectory(self, "選擇文件夾")
        if path:
            self.folder_input.setText(path)
 
    def start_search(self):
        if self.search_thread and self.search_thread.isRunning():
            return
 
        folder = self.folder_input.text()
        exts = self.ext_input.text().strip().split(";")
        keyword = self.keyword_input.text().strip()
 
        if not all([folder, exts, keyword]):
            QMessageBox.critical(self, "錯誤", "請?zhí)顚懰兴阉鳁l件")
            return
 
        self.tree.clear()
        self.match_list.clear()
        self.current_matches = []
        self.update_counts()
        self.start_time = time.time()
 
        self.search_thread = SearchWorker(folder, exts, keyword)
        self.search_thread.update_file.connect(self.add_file_result)
        self.search_thread.finished.connect(self.on_search_finished)
        self.search_thread.start()
        self.btn_search.setEnabled(False)
 
    def add_file_result(self, data):
        item = QTreeWidgetItem()
        item.setText(0, data["name"])
        item.setText(1, data["size"])
        item.setText(2, data["path"])
        self.tree.addTopLevelItem(item)
        self.file_count.setText(f"文件總數(shù): {self.tree.topLevelItemCount()}")
 
    def on_search_finished(self):
        self.btn_search.setEnabled(True)
        elapsed = time.time() - self.start_time
        self.time_label.setText(f"耗時: {elapsed:.2f}秒")
 
    def single_file_search(self):
        path = self.single_input.text()
        keyword = self.keyword_input.text().strip()
 
        if not os.path.isfile(path):
            QMessageBox.critical(self, "錯誤", "無效的文件路徑")
            return
 
        self.match_list.clear()
        self.current_matches = []
        self.file_reader = FileReader(path, keyword)
        self.file_reader.update_line.connect(self.match_list.addItem)
        self.file_reader.finished.connect(lambda: (
            self.line_count.setText(f"匹配行數(shù): {self.match_list.count()}"),
            self.current_matches.extend(self.file_reader.results)
        ))
        self.file_reader.start()
 
    def on_tree_double_click(self):
        item = self.tree.currentItem()
        if not item: return
         
        path = item.text(2)
        keyword = self.keyword_input.text().strip()
        self.match_list.clear()
        self.current_matches = []
         
        self.file_reader = FileReader(path, keyword)
        self.file_reader.update_line.connect(self.match_list.addItem)
        self.file_reader.finished.connect(lambda: (
            self.line_count.setText(f"匹配行數(shù): {self.match_list.count()}"),
            self.current_matches.extend(self.file_reader.results)
        ))
        self.file_reader.start()
 
    def on_list_double_click(self):
        index = self.match_list.currentRow()
        if 0 <= index < len(self.current_matches):
            self.detail_text.setPlainText(self.current_matches[index])
 
    def search_all_files(self):
        paths = []
        root = self.tree.invisibleRootItem()
        for i in range(root.childCount()):
            item = root.child(i)
            paths.append(item.text(2))
 
        keyword = self.keyword_input.text().strip()
        if not keyword:
            QMessageBox.critical(self, "錯誤", "請輸入搜索關鍵字")
            return
 
        self.match_list.clear()
        self.current_matches = []
        self.all_files_reader = AllFilesReader(paths, keyword)
        self.all_files_reader.update_line.connect(self.match_list.addItem)
        self.all_files_reader.finished.connect(lambda: (
            self.line_count.setText(f"匹配行數(shù): {self.match_list.count()}"),
            self.current_matches.extend(self.file_reader.results) if self.file_reader else None
        ))
        self.all_files_reader.start()
 
    def export_match_list(self):
        keyword = self.keyword_input.text().strip() or "search"
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        filename = f"{keyword}_{timestamp}.txt"
        desktop = f"D:/桌面/"
        path = os.path.join(desktop, filename)
 
        with open(path, 'w', encoding='utf-8') as f:
            for i in range(self.match_list.count()):
                f.write(self.match_list.item(i).text() + "\n")
 
        QMessageBox.information(self, "導出完成", f"文件已保存到:{path}")
 
    def export_tree_info(self):
        items = []
        root = self.tree.invisibleRootItem()
        for i in range(root.childCount()):
            item = root.child(i)
            items.append("\t".join([
                item.text(0),
                item.text(1),
                item.text(2)
            ]))
 
        timestamp = time.strftime("%Y%m%d_%H%M%S")
        filename = f"tree_export_{timestamp}.txt"
        desktop = f"D:/桌面/"
        path = os.path.join(desktop, filename)
 
        with open(path, 'w', encoding='utf-8') as f:
            f.write("\n".join(items))
 
        QMessageBox.information(self, "導出完成", f"樹結構已保存到:{path}")
 
    def import_tree_info(self):
        path, _ = QFileDialog.getOpenFileName(self, "選擇導入文件", "", "文本文件 (*.txt)")
        if not path:
            return
 
        self.tree.clear()
        with open(path, 'r', encoding='utf-8') as f:
            for line in f:
                parts = line.strip().split('\t')
                if len(parts) != 3:
                    continue
                item = QTreeWidgetItem()
                item.setText(0, parts[0])
                item.setText(1, parts[1])
                item.setText(2, parts[2])
                self.tree.addTopLevelItem(item)
        self.file_count.setText(f"文件總數(shù): {self.tree.topLevelItemCount()}")
 
    def update_counts(self):
        self.file_count.setText(f"文件總數(shù): {self.tree.topLevelItemCount()}")
        self.line_count.setText(f"匹配行數(shù): {self.match_list.count()}")
 
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

6.總結

這是一個基于PyQt6開發(fā)的文件搜索與內容匹配工具。該工具不僅支持高效的文件查找,還能通過關鍵字匹配文件內容,并提供詳細的匹配結果展示和導出功能。利用PyQt的多線程特性,程序在執(zhí)行搜索任務時能夠保持界面的響應性,大大提升了用戶體驗。

未來的改進方向包括:

增強搜索效率:可以增加更多的文件搜索選項,如模糊匹配或正則表達式支持,以滿足更復雜的查找需求。

界面優(yōu)化:加入進度條或其他UI元素,實時反饋搜索進度。

功能擴展:支持更多的文件操作,如批量重命名、批量刪除等。

以上就是基于Python開發(fā)高效文件搜索與內容匹配工具的詳細內容,更多關于Python文件搜索與內容匹配的資料請關注腳本之家其它相關文章!

相關文章

  • python中的編碼知識整理匯總

    python中的編碼知識整理匯總

    這篇文章主要介紹了python中的編碼知識整理匯總的相關資料,需要的朋友可以參考下
    2016-01-01
  • Python自動化完成tb喵幣任務的操作方法

    Python自動化完成tb喵幣任務的操作方法

    2019雙十一,tb推出了新的活動,商店喵幣,看了一下每天都有幾個任務來領取喵幣,從而升級店鋪賺錢,然而我既想賺紅包又不想干苦力,遂使用python來進行手機自動化操作,需要的朋友跟隨小編一起看看吧
    2019-10-10
  • python抓取網(wǎng)頁內容并進行語音播報的方法

    python抓取網(wǎng)頁內容并進行語音播報的方法

    今天小編就為大家分享一篇python抓取網(wǎng)頁內容并進行語音播報的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-12-12
  • 通俗易懂詳解Python基礎五種下劃線作用

    通俗易懂詳解Python基礎五種下劃線作用

    本來而言,這個問題網(wǎng)上很多資料,但是網(wǎng)上資料都是復制來復制去,很多話大家其實都不是很明白的,或者拿著官方文檔翻譯過來的,讓人看的非常迷糊。今天用通俗好懂表述解釋下這幾種情況
    2021-10-10
  • Pandas保存csv數(shù)據(jù)的三種方式詳解

    Pandas保存csv數(shù)據(jù)的三種方式詳解

    CSV文件以純文本形式存儲表格數(shù)據(jù)(數(shù)字和文本),是一種通用的、相對簡單的文件格式,被用戶、商業(yè)和科學廣泛應用。本文介紹了三種Pandas保存CSV文件數(shù)據(jù)的方法,需要的可以參考一下
    2022-03-03
  • python3+telnetlib實現(xiàn)簡單自動測試示例詳解

    python3+telnetlib實現(xiàn)簡單自動測試示例詳解

    telnetlib 模塊提供一個實現(xiàn)Telnet協(xié)議的類 Telnet,本文重點給大家介紹python3+telnetlib實現(xiàn)簡單自動測試示例詳解,需要的朋友可以參考下
    2021-08-08
  • Python configparser模塊配置文件過程解析

    Python configparser模塊配置文件過程解析

    這篇文章主要介紹了Python configparser模塊配置文件過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • 如何獲取numpy的第一個非0元素索引

    如何獲取numpy的第一個非0元素索引

    這篇文章主要介紹了如何獲取numpy的第一個非0元素索引,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • 詳解Python計算機視覺 圖像扭曲(仿射扭曲)

    詳解Python計算機視覺 圖像扭曲(仿射扭曲)

    這篇文章主要介紹了Python計算機視覺 圖像扭曲(仿射扭曲),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • python?requests模塊封裝詳解

    python?requests模塊封裝詳解

    requests是一個常用的HTTP請求庫,可以方便地向網(wǎng)站發(fā)送HTTP請求,并獲取響應結果,本文主要和大家介紹一下requests模塊的使用與封裝,需要的可以參考下
    2023-09-09

最新評論