FILE *文件指针 粗略介绍

本文详细介绍了C语言中文件指针的概念及使用方法。通过定义文件指针,可以实现对文件的各种操作,如读取、写入等。文章解释了如何定义文件指针,并通过示例展示了其在实际编程中的应用。

 

在程序中,看到了这样的内容,

FILE *stream; 

解释如下:

文件指针在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。

通过文件指针就可对它所指的文件进行各种操作。

定义说明文件指针的一般形式为:

FILE *指针变量标识符;

其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。

例如:FILE *fp;表示fp是指向FILE结构的指针变量,通过fp即可找存放某个文件信息的结构变量,然后按结构变量提供的信息找到该文件,实施对文件的操作。

习惯上也笼统地把fp称为指向一个文件的指针。

import os import can from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit, QFileDialog, QMessageBox, QCheckBox, QProgressBar ) from PyQt6.QtCore import Qt, QThread, pyqtSignal, pyqtSlot, QTimer from PyQt6.QtGui import QFont class BLFConverterWorker(QThread): """转换工作线程""" # 定义信号 progress_updated = pyqtSignal(int) # 进度更新信号 log_message = pyqtSignal(str) # 日志消息信号 conversion_finished = pyqtSignal(bool, str) # 转换完成信号 def __init__(self, blf_file_path, log_file_path, show_channel): super().__init__() self.blf_file_path = blf_file_path self.log_file_path = log_file_path self.show_channel = show_channel self.is_cancelled = False self._running = True # 线程运行状态标志 def run(self): """工作线程的主要执行函数""" try: self.log_message.emit("开始转换BLF文件...") self.log_message.emit(f"源文件: {self.blf_file_path}") self.log_message.emit(f"目标文件: {self.log_file_path}") # 获取文件总数(如果是目录的话) file_count = 0 if os.path.isdir(self.blf_file_path): file_count = len([f for f in os.listdir(self.blf_file_path) if f.endswith('.blf')]) else: file_count = 1 current_file = 0 # 打开输出文件 with open(self.log_file_path, 'w', encoding='utf-8') as f: # 遍历 BLF 目录 if os.path.isdir(self.blf_file_path): files = [f for f in os.listdir(self.blf_file_path) if f.endswith('.blf')] total_files = len(files) for i, filename in enumerate(files): if not self._running or self.is_cancelled: self.log_message.emit("转换已取消") self.conversion_finished.emit(False, "转换已取消") return blf_file_path = os.path.join(self.blf_file_path, filename) self.log_message.emit(f"正在处理文件: {filename}") # 更新进度 progress = int((i + 1) / total_files * 100) self.progress_updated.emit(progress) log_data = self.convert_single_blf(blf_file_path) if log_data: f.write(log_data) current_file += 1 self.log_message.emit(f"文件 {filename} 处理完成") self.log_message.emit(f"所有数据已合并写入文件: {self.log_file_path}") else: if not self._running or self.is_cancelled: self.log_message.emit("转换已取消") self.conversion_finished.emit(False, "转换已取消") return self.log_message.emit("正在处理单个文件...") log_data = self.convert_single_blf(self.blf_file_path) if log_data: f.write(log_data) if self._running and not self.is_cancelled: self.conversion_finished.emit(True, "转换完成") except Exception as e: if self._running: error_msg = f"转换过程中发生错误: {str(e)}" self.log_message.emit(error_msg) self.conversion_finished.emit(False, error_msg) def convert_single_blf(self, blf_path): """转换单个BLF文件""" try: # 创建BLF读取器 reader = can.BLFReader(blf_path) output_data = [] # 获取总消息数用于进度计算 total_messages = 0 try: # 尝试获取文件大小来估算消息数量 total_messages = reader.file_size // 100 # 粗略估算 except: pass # 遍历每条CAN消息 message_count = 0 for msg in reader: if not self._running or self.is_cancelled: return None # 格式化数据为十六进制字符串 data_hex = ' '.join([f"{byte:02X}" for byte in msg.data]) # 根据是否显示通道来决定输出格式 if self.show_channel: # 显示通道:时间戳后面空四格,通道包括自身空五格 output_data.append( f"{msg.timestamp:.6f} {msg.channel:<5}0x{msg.arbitration_id:03X} {msg.dlc:<5}{data_hex}\n") else: # 不显示通道:时间戳后面空四格 output_data.append( f"{msg.timestamp:.6f} 0x{msg.arbitration_id:03X} {msg.dlc:<5}{data_hex}\n") message_count += 1 # 定期更新进度(每处理1000条消息更新一次) if message_count % 1000 == 0: progress = min(int(message_count / (total_messages or 1) * 100), 100) if self._running and not self.is_cancelled: self.progress_updated.emit(progress) if self._running and not self.is_cancelled: self.log_message.emit( f"成功处理文件: {blf_path} (共处理 {message_count} 条消息)") return ''.join(output_data) except FileNotFoundError: if self._running: self.log_message.emit(f"错误: 文件不存在 - {blf_path}") return None except can.CanError as e: if self._running: self.log_message.emit(f"CAN错误: {str(e)}") return None except Exception as e: if self._running: self.log_message.emit(f"未知错误: {str(e)}") return None def stop(self): """停止线程""" self.is_cancelled = True self._running = False class BLFConverterWidget(QWidget): def __init__(self): super().__init__() self.init_ui() self.blf_file_path = "" self.log_file_path = "" self.show_channel = True # 默认显示通道 self.worker = None # 工作线程 self.is_converting = False # 是否正在转换 self.timer = QTimer() # 用于定期检查线程状态 def init_ui(self): layout = QVBoxLayout() # BLF文件选择 blf_layout = QHBoxLayout() blf_layout.addWidget(QLabel("BLF文件:")) self.blf_path_edit = QLineEdit() self.blf_path_edit.setPlaceholderText("请选择BLF文件或目录") blf_browse_btn = QPushButton("浏览") blf_browse_btn.clicked.connect(self.browse_blf_file) blf_layout.addWidget(self.blf_path_edit) blf_layout.addWidget(blf_browse_btn) # LOG文件选择 log_layout = QHBoxLayout() log_layout.addWidget(QLabel("LOG文件:")) self.log_path_edit = QLineEdit() self.log_path_edit.setPlaceholderText("请选择LOG文件保存路径") log_browse_btn = QPushButton("浏览") log_browse_btn.clicked.connect(self.browse_log_file) log_layout.addWidget(self.log_path_edit) log_layout.addWidget(log_browse_btn) # 是否显示通道选项 channel_layout = QHBoxLayout() self.channel_checkbox = QCheckBox("显示通道") self.channel_checkbox.setChecked(True) # 默认选中 self.channel_checkbox.stateChanged.connect(self.on_channel_checkbox_changed) channel_layout.addWidget(self.channel_checkbox) channel_layout.addStretch() # 添加伸缩项,使复选框靠左对齐 # 进度条 self.progress_bar = QProgressBar() self.progress_bar.setVisible(False) # 初始隐藏 self.progress_bar.setTextVisible(True) self.progress_bar.setFormat("转换进度: %p%") # 操作按钮 button_layout = QHBoxLayout() self.convert_btn = QPushButton("开始转换") self.convert_btn.clicked.connect(self.convert_blf_to_log) self.cancel_btn = QPushButton("取消转换") self.cancel_btn.clicked.connect(self.cancel_conversion) self.cancel_btn.setVisible(False) # 初始隐藏 button_layout.addWidget(self.convert_btn) button_layout.addWidget(self.cancel_btn) # 日志输出 self.log_output = QTextEdit() self.log_output.setPlaceholderText("转换日志输出...") self.log_output.setReadOnly(True) # 设置日志输出字体为等宽字体,便于对齐查看 font = QFont("Courier New", 10) self.log_output.setFont(font) # 添加到主布局 layout.addLayout(blf_layout) layout.addLayout(log_layout) layout.addLayout(channel_layout) # 添加通道选择布局 layout.addWidget(self.progress_bar) # 添加进度条 layout.addLayout(button_layout) layout.addWidget(self.log_output) self.setLayout(layout) def on_channel_checkbox_changed(self, state): """当通道复选框状态改变时调用""" self.show_channel = (state == Qt.CheckState.Checked.value) # PyQt6中使用value属性 def browse_blf_file(self): """浏览BLF文件或目录""" # 首先尝试选择目录 directory = QFileDialog.getExistingDirectory( self, "选择BLF文件所在目录", "", QFileDialog.Option.ShowDirsOnly ) if directory: self.blf_file_path = directory self.blf_path_edit.setText(directory) self.log_output.append(f"已选择BLF目录: {directory}") return # 如果目录选择取消,尝试选择单个文件 file_path, _ = QFileDialog.getOpenFileName( self, "选择BLF文件", "", "BLF Files (*.blf);;All Files (*)" ) if file_path: self.blf_file_path = file_path self.blf_path_edit.setText(file_path) self.log_output.append(f"已选择BLF文件: {file_path}") def browse_log_file(self): file_path, _ = QFileDialog.getSaveFileName( self, "保存LOG文件", "", "LOG Files (*.log);;All Files (*)" ) if file_path: self.log_file_path = file_path self.log_path_edit.setText(file_path) self.log_output.append(f"LOG文件保存路径: {file_path}") # def clear_files(self): # self.blf_path_edit.clear() # self.log_path_edit.clear() # self.log_output.clear() # self.blf_file_path = "" # self.log_file_path = "" # self.log_output.append("文件信息已清空") def convert_blf_to_log(self): """开始转换按钮点击事件""" if self.is_converting: return if not self.blf_file_path: QMessageBox.warning(self, "警告", "请先选择BLF文件或目录") return if not self.log_file_path: QMessageBox.warning(self, "警告", "请先选择LOG文件保存路径") return # 检查选择的路径是否存在 if not os.path.exists(self.blf_file_path): QMessageBox.warning(self, "警告", "选择的BLF路径不存在") return # 检查是否为文件或目录 if not (os.path.isfile(self.blf_file_path) or os.path.isdir(self.blf_file_path)): QMessageBox.warning(self, "警告", "选择的路径既不是文件也不是目录") return # 禁用转换按钮,显示取消按钮 self.convert_btn.setEnabled(False) self.cancel_btn.setVisible(True) self.is_converting = True # 显示进度条 self.progress_bar.setVisible(True) self.progress_bar.setValue(0) # 创建并启动工作线程 self.worker = BLFConverterWorker( self.blf_file_path, self.log_file_path, self.show_channel ) # 连接信号 self.worker.progress_updated.connect(self.update_progress) self.worker.log_message.connect(self.append_log_message) self.worker.conversion_finished.connect(self.conversion_result) # 启动线程 self.worker.start() def update_progress(self, progress): """更新进度条""" if self.progress_bar and self.progress_bar.isVisible(): self.progress_bar.setValue(progress) def append_log_message(self, message): """添加日志消息""" if self.log_output: self.log_output.append(message) # 滚动到最新消息 self.log_output.verticalScrollBar().setValue( self.log_output.verticalScrollBar().maximum() ) def conversion_result(self, success, message): """转换完成回调""" self.is_converting = False self.convert_btn.setEnabled(True) self.cancel_btn.setVisible(False) self.progress_bar.setVisible(False) if success: self.log_output.append("转换完成!") else: self.log_output.append(f"转换失败: {message}") # 重置进度条 if self.progress_bar: self.progress_bar.setValue(0) # 清理线程引用 if self.worker: self.worker.quit() self.worker.wait() self.worker.deleteLater() self.worker = None def cancel_conversion(self): """取消转换""" if self.worker and self.is_converting: self.log_output.append("正在取消转换...") # 停止线程 self.worker.stop() # 等待线程结束 if self.worker.isRunning(): self.worker.wait(5000) # 等待最多5秒 self.is_converting = False self.convert_btn.setEnabled(True) self.cancel_btn.setVisible(False) self.progress_bar.setVisible(False) self.progress_bar.setValue(0) self.log_output.append("转换已取消") # 清理线程引用 if self.worker: self.worker.quit() self.worker.wait() self.worker.deleteLater() self.worker = None def closeEvent(self, event): """窗口关闭事件,确保线程正确结束""" if self.worker and self.worker.isRunning(): self.worker.stop() # self.worker.wait(5000) # 等待最多5秒 self.worker.deleteLater() event.accept() def __del__(self): """析构函数,确保资源清理""" if self.worker and self.worker.isRunning(): self.worker.stop() self.worker.wait() self.worker.deleteLater() 这里的代码,进度条达到100后,过了很久文件才写入到log里,帮我优化一下,解析完blf文件后,数据写入到log文件后才达到100
最新发布
12-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值