用于生成软著的空行删除器

众所周知,申请软件著作权登记证书时,所提交的源代码不能含有空行,否则有概率不通过。以下代码可以快速导入代码文件,删除空行并将所有文件内容合并到一个TXT文件中:
开源地址

import sys
import os
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QListWidget, 
    QPushButton, QFileDialog, QMessageBox, QListWidgetItem
)
from PyQt5.QtCore import Qt

class FileMergerApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("文件合并工具")
        self.setGeometry(100, 100, 500, 400)
        self.setAcceptDrops(True)
        
        # 创建UI组件
        self.list_widget = QListWidget()
        self.list_widget.setDragEnabled(True)
        self.list_widget.setAcceptDrops(False)
        self.list_widget.setSelectionMode(QListWidget.ExtendedSelection)
        
        self.btn_generate = QPushButton("生成 source.txt")
        self.btn_clear = QPushButton("清空列表")
        self.btn_add = QPushButton("添加文件")
        
        # 设置布局
        layout = QVBoxLayout()
        layout.addWidget(self.list_widget)
        layout.addWidget(self.btn_generate)
        layout.addWidget(self.btn_clear)
        layout.addWidget(self.btn_add)
        self.setLayout(layout)
        
        # 连接信号
        self.btn_generate.clicked.connect(self.generate_file)
        self.btn_clear.clicked.connect(self.clear_list)
        self.btn_add.clicked.connect(self.add_files)
    
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
        else:
            event.ignore()
    
    def dropEvent(self, event):
        for url in event.mimeData().urls():
            file_path = url.toLocalFile()
            self.add_file_to_list(file_path)
        event.acceptProposedAction()
    
    def add_file_to_list(self, file_path):
        # 检查文件是否已存在列表中
        if not any(self.list_widget.item(i).data(Qt.UserRole) == file_path 
                  for i in range(self.list_widget.count())):
            # 创建新的列表项
            item = QListWidgetItem(os.path.basename(file_path))
            item.setData(Qt.UserRole, file_path)  # 存储完整路径
            self.list_widget.addItem(item)
    
    def add_files(self):
        files, _ = QFileDialog.getOpenFileNames(
            self, "选择文件", "", "所有文件 (*.*)"
        )
        for file in files:
            self.add_file_to_list(file)
    
    def clear_list(self):
        self.list_widget.clear()
    
    def generate_file(self):
        if self.list_widget.count() == 0:
            QMessageBox.warning(self, "警告", "文件列表为空!")
            return
        
        try:
            with open("source.txt", "w", encoding="utf-8") as output_file:
                for i in range(self.list_widget.count()):
                    file_path = self.list_widget.item(i).data(Qt.UserRole)
                    try:
                        with open(file_path, "r", encoding="utf-8") as input_file:
                            for line in input_file:
                                stripped_line = line.rstrip()
                                if stripped_line:  # 检查是否非空行
                                    output_file.write(stripped_line + "\n")
                    except UnicodeDecodeError:
                        # 尝试使用其他常见编码
                        try:
                            with open(file_path, "r", encoding="latin-1") as input_file:
                                for line in input_file:
                                    stripped_line = line.rstrip()
                                    if stripped_line:
                                        output_file.write(stripped_line + "\n")
                        except Exception as e:
                            QMessageBox.critical(
                                self, "错误", 
                                f"无法读取文件(编码问题): {file_path}\n{str(e)}"
                            )
                            return
                    except Exception as e:
                        QMessageBox.critical(
                            self, "错误", 
                            f"读取文件时出错: {file_path}\n{str(e)}"
                        )
                        return
            
            QMessageBox.information(
                self, "成功", 
                f"文件已生成: source.txt\n位置: {os.getcwd()}"
            )
        except Exception as e:
            QMessageBox.critical(
                self, "错误", 
                f"写入输出文件时出错: {str(e)}"
            )

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = FileMergerApp()
    window.show()
    sys.exit(app.exec_())
无标签