手把手教你用Rust实现一个现代化的命令行十六进制查看器
最近对rust语言比较感兴趣,也在探索它的各种优秀特性,学习了一段时间它的基础语法之后,最近正打算写个小项目练练手。考虑到日常工作中经常需要分析各种ELF格式的二进制文件,而传统的xxd工具界面相对简陋,我决定用Rust写一个现代化的终端十六进制查看器。最终的实现效果感觉还不错,所以就把开发过程和运行效果,跟大家做个分享。
为什么选择Rust?
对于这种系统级工具,Rust是一个非常好的选择:
- 零成本抽象:性能与C/C++相当
- 内存安全:避免缓冲区溢出等问题
- 优秀的生态系统:有丰富的第三方库可用
- 跨平台支持:一次编写到处编译
功能需求
我们要实现的hex viewer需要具备以下功能:
- 显示文件的十六进制内容,同时展示对应的ASCII字符
- 支持键盘导航(上下滚动、翻页)
- 搜索功能(支持文本搜索)
- 美观的TUI界面
- 命令行参数解析
技术选型
为了快速开发,我们使用了一些优秀的第三方库:
这些库都是Rust生态中相应领域的首选方案。
核心实现
数据结构设计
首先我们需要定义程序的核心数据结构:
struct HexViewer {
file_data: Vec<u8>, // 存储文件的所有字节
scroll_offset: usize, // 滚动偏移量
search_term: String, // 当前搜索词
search_results: Vec<usize>, // 搜索结果位置列表
current_search_index: usize, // 当前聚焦的搜索结果索引
bytes_per_line: usize, // 每行显示多少字节
input_mode: InputMode, // 输入模式(导航/搜索)
search_input: String, // 正在输入的搜索词
case_sensitive: bool, // 是否区分大小写
}
TUI界面渲染
使用ratatui库我们可以创建美观的终端界面。主要分为两个区域:
- 主显示区域:展示hex内容
- 底部状态栏:显示状态信息和提示
fn render_ui(f: &mut Frame, app: &HexViewer) {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Min(1),
Constraint::Length(1), // 状态栏
])
.split(f.area());
// 主显示区域
let hex_block = Block::default()
.borders(Borders::ALL)
.title(Title::from("Hex Viewer").alignment(Alignment::Center));
// 构建显示行
let mut lines = Vec::new();
let visible_lines = app.visible_lines_count(chunks[0].height as usize);
for i in 0..visible_lines {
if app.scroll_offset + i < app.total_lines() {
let offset = (app.scroll_offset + i) * app.bytes_per_line;
let line = app.hex_line(offset);
lines.push(line);
} else {
lines.push(Line::from(""));
}
}
let paragraph = Paragraph::new(lines)
.block(hex_block)
.wrap(Wrap { trim: false });
f.render_widget(paragraph, chunks[0]);
// 状态栏渲染逻辑...
}
键盘事件处理
为了提供良好的用户体验,我们需要处理各种键盘事件:
fn handle_key_event(event: KeyEvent, app: &mut HexViewer, height: usize) -> bool {
match app.input_mode {
InputMode::Navigation => {
match event.code {
KeyCode::Char('q') | KeyCode::Esc => return false,
KeyCode::Char('j') | KeyCode::Down => {
app.scroll_down(1, height)
},
KeyCode::Char('k') | KeyCode::Up => {
app.scroll_up(1)
},
KeyCode::PageDown => {
app.scroll_down(height / 2, height);
},
KeyCode::PageUp => {
app.scroll_up(height / 2);
},
KeyCode::Char('/') => {
app.enter_search_mode();
},
KeyCode::Char('n') => {
app.next_search_result(height);
},
KeyCode::Char('N') => {
app.prev_search_result(height);
},
_ => {}
}
}
InputMode::Searching => {
match event.code {
KeyCode::Enter => {
app.search();
app.input_mode = InputMode::Navigation;
},
KeyCode::Esc => {
app.input_mode = InputMode::Navigation;
},
KeyCode::Backspace => {
app.search_input.pop();
},
KeyCode::Char(c) => {
app.search_input.push(c);
},
KeyCode::Tab => {
app.toggle_case_sensitivity();
}
_ => {}
}
}
}
true
}
搜索功能实现
搜索是这个工具的一个亮点功能,它不仅支持精确匹配,还能在结果间跳转:
fn search(&mut self) {
self.search_term = self.search_input.clone();
if self.search_term.is_empty() {
self.search_results.clear();
return;
}
self.search_results.clear();
// 根据是否区分大小写进行搜索
if self.case_sensitive {
// 区分大小写的搜索
let search_bytes = self.search_term.as_bytes();
for i in 0..=self.file_data.len().saturating_sub(search_bytes.len()) {
if self.file_data[i..].starts_with(search_bytes) {
self.search_results.push(i);
}
}
} else {
// 不区分大小写的搜索
// 将搜索词转为小写
let search_term_lower = self.search_term.to_lowercase();
let search_bytes = search_term_lower.as_bytes();
// 对于不区分大小写的搜索,我们仍然在字节级别进行操作
for i in 0..=self.file_data.len().saturating_sub(search_bytes.len()) {
// 获取当前窗口的字节并转换为字符串再转为小写进行比较
let current_slice = &self.file_data[i..i + search_bytes.len()];
if let Ok(current_str) = std::str::from_utf8(current_slice) {
if current_str.to_lowercase().starts_with(&search_term_lower) {
self.search_results.push(i);
}
}
// 如果不是有效的UTF-8,则跳过这个位置
}
}
self.current_search_index = 0;
}
运行效果
通过简单的测试可以看到,我们的hex viewer运行良好。它不仅能清晰地展示文件的十六进制内容,还提供了便捷的导航和搜索功能,同时还支持↑↓方向键翻页。

当使用搜索功能时,匹配的结果会被高亮显示,并且可以使用n/N坚在多个匹配项之间切换,大大提高了查找特定内容的效率和用户体验。

同时,还支持通过tab键配置大小写敏感性,如下图所示,是忽略大小写时的elf搜索结果,明显比上张图中大小的ELF搜索结果要多。

总结
通过这个项目,我深刻体会到了Rust在系统编程方面的优势:
- 强大的类型系统帮助我们在编译期就发现很多潜在问题
- 丰富的生态系统让开发变得高效
- 内存安全保障让我们可以专注于业务逻辑而不是内存管理
这个hex viewer虽然功能相对简单,但它展示了如何使用Rust构建一个实用的命令行工具。后续还可以添加更多功能,比如:
- 编辑功能
- 多种显示格式(十进制、八进制等)
- 导出功能
- 更复杂的搜索选项,如正则表达式等。
想了解更多关于Rust语言的知识及应用,可前往华为开放原子旋武开源社区(https://xuanwu.openatom.cn/),了解更多资讯~
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)