通过C++程序实现光驱的自动化刻录和读取
文章目录
- ISO文件格式
- 光盘的基本概念
- 光盘种类特点
- DVD+R光盘使用
- windows调用
- Linux调用
- Linux平台下用到的C++库:
- 读取设备驱动列表
- 向光驱中写文件
数字存储媒体快速发展的今天,光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还有在使用。
ISO文件格式
在刻录普通文件到光盘时,并不一定需要将它们制作成ISO文件。你可以使用光盘刻录软件直接添加文件到光盘中,而无需事先制作ISO文件。而如果你希望确保光盘上的文件与多个操作系统兼容或者需要创建一个可引导的光盘,那么制作成ISO文件可能是一个更好的选择。在这种情况下,你可以在刻录软件中选择制作ISO映像,然后再将该ISO文件刻录到光盘上。
制作成ISO文件的优点:
1.保持文件的完整性和一直性 2.兼容多个操作系统 3.可以跨平台使用 4.方便管理和存储
光盘的基本概念
Session(会话): 会话是光盘上的一个逻辑刻录单元。每次进行刻录,都会创建一个新的会话。
Track(轨道): 轨道是光盘上的一个圆形路径,沿着这个路径数据被刻录和读取。光盘上通常有许多并行的轨道,每个轨道都划分为一系列的扇区。
Sector(扇区): 扇区是光盘上最小的物理存储单元,是数据的基本单元。一个光盘被划分为许多扇区,每个扇区通常包含2048字节(2KB)的数据。
光盘种类特点
根据光盘的写入类型、用途、容量,光盘分为很多种类,详细分类如下:
CD(Compact Dis) 典型容量为700MB
1.CD-ROM(Read-Only Memory): 只读光盘 用于分发软件、应用和视频
2.CD-R(Recordable): 可以一次性写入, 写入之后不能修改,常用于备份音乐和数据
3.CD-RW(ReWritable): 可多次擦写和重写,适合频繁修改数据
DVD(Digital Versaatile Disc) 单层容量为4.7GB 双层容量为8.5GB
1.DVD-ROM: 类似于CD-ROM,只读光盘,用于电影、软件等的分发。
2.DVD-R: 一次写入型,用于备份和分发。
3.DVD+R: 一次写入型,与DVD-R相似。
4.DVD-RW: 可多次擦写和重写。
5.DVD+RW: 与DVD-RW类似。
Blu-ray Disc(BD) 单层容量为25GB 双层容量为50GB
1.BD-ROM: 用于高清电影和软件分发的一次写入型。
2.BD-R: 一次写入型,用于高容量数据备份。
BD-RE(Rewritable): 可多次擦写和重写,适用于频繁修改的数据。
HD DVD(已基本淘汰)
HD DVD-ROM: 用于高清电影和软件分发的一次写入型。
HD DVD-R: 一次写入型,用于备份和分发。
HD DVD-RW: 可多次擦写和重写。
Mini光盘
Mini CD 和 Mini DVD: 较小尺寸的光盘,用于特定设备和应用。
DVD+R光盘使用
这里以DVD+R光盘为例说明一下,光盘的使用和初始化,初始化界面如下:
1.初始化为U盘模式之后我们就可以使用光盘反复读写文件了,但每次读写都会消耗有限的磁盘读写空间。
2.初始化为用于CD/DVD播放机模式的时候,就只可以写入一次了,再次写入会将磁盘损坏。
DVD+R采用了一种称为Incremental Sequential Recording(增量顺序写入)写入方式,该方式不允许在会话关闭后继续写入。在DVD+R上创建一个会话后,一旦会话被关闭(Finalized),就不能再向该会话中追加写入新的数据。
windows调用
Windows操作光驱需要使用IMAPI(Image Mastering API)
IMAPI是一个用于创建和写入光盘映像文件的Windows API。它可以用于将文件和文件夹内容写入光盘,并创建可引导光盘。
1.创建映像对象
// 初始化 COM
CoInitializeEx(NULL, COINIT_MULTITHREADED); IDiscMaster* pDiscMaster = NULL;
HRESULT hr = CoCreateInstance(__uuidof(MsftDiscMaster2), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiscMaster2), (void**)&pDiscMaster); if (SUCCEEDED(hr)) {// 成功创建
} else {// 创建失败
}
2.获取光驱数量和ID
IDiscMaster* pDiscMaster = NULL;
long totalDevices = 0; //光驱数量
HRESULT hr = CoCreateInstance(__uuidof(MsftDiscMaster2), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiscMaster2), (void**)&pDiscMaster);
hr = m_discMaster->get_Count(&totalDevices);
BSTR uniqueID = NULL; //光驱的ID
hr = m_discMaster->get_Item(0, &uniqueID);
3.初始化刻录类
IDiscRecorder2* discRecorder = NULL;
BSTR recordUniqueId;
SAFEARRAY* m_volumePathNames;
HRESULT hr = CoCreateInstance(__uuidof(MsftDiscRecorder2), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDiscRecorder2), (void**)&discRecorder);
if (FAILED(hr)) return false;//初始化刻录类
discRecorder->InitializeDiscRecorder(recordUniqueId);//获取卷
discRecorder->get_VolumePathNames(&m_volumePathNames);
参考项目
Linux调用
Linux平台下用到的C++库:
1.libburn
libburn 是一个用于写入光盘的库,它支持 CD、DVD 和 Blu-ray。它提供了 C 接口,可以在 C++ 中使用。libburn 允许你创建数据和音频光盘,并提供了对光驱的低级别访问。
https://dev.lovelyhq.com/libburnia/libburn
sudo apt-get install libburn-dev
2.libcdio
libcdio 提供了一种接口,用于访问 CD-ROM 和 DVD-ROM 设备。它包括一组 C 函数,允许你读取光盘的数据、音轨等信息。libcdio 还包含用于访问 ISO-9660 文件系统的功能。
https://www.gnu.org/software/libcdio/
sudo apt-get install libcdio-dev
3.libudev
libudev 是一个用于管理设备的库,你可以使用它来检测和获取有关设备的信息,包括 USB 光驱。你可以通过监听 udev 事件来获取插拔 USB 设备的通知。
sudo apt-get update
sudo apt-get install libudev-dev
读取设备驱动列表
1.使用libburn库读设备列表
使用libburn库读取USB光驱设备时异常,无法读取USB光驱。
参考项目
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "libburn/libburn.h"using namespace burn;
using namespace std;int main(int argc, char const *argv[])
{struct burn_drive_info *drive_list;unsigned int drive_count = 0;int ret;//初始化libburn if (!burn_initialize()){cout << "init libburn failed" << endl;}//获取光驱的数量while(!burn_drive_scan(&drive_list, &drive_count));usleep(100002);if(drive_count <=0){cout << "error to scan drive" << endl;return -1;}//抓取光驱ret = burn_drive_grab(drive_list[0].drive, 1);if(!ret){cout << "error to grab the drive";return -1;}//释放光驱burn_drive_release(drive_list[0].drive, 1);//结束burn_finish();return 0;
}
2.使用liudev获取设备列表
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <libudev.h>
#include <linux/cdrom.h>
#include <fcntl.h>
#include <sys/ioctl.h>
/*** 获取所有光驱的列表*/
std::vector<std::string> GetOpticalDriveList()
{udev* udev_context = udev_new();if (!udev_context)return {};std::vector<std::string> drives;udev_enumerate* enumerate = udev_enumerate_new(udev_context);if (enumerate){udev_enumerate_add_match_subsystem(enumerate, "block");udev_enumerate_add_match_property(enumerate, "ID_CDROM_DVD", "1");udev_enumerate_scan_devices(enumerate);udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);udev_list_entry* dev_list_entry;udev_list_entry_foreach(dev_list_entry, devices){const char* path = udev_list_entry_get_name(dev_list_entry);udev_device* device = udev_device_new_from_syspath(udev_context, path);const char* devnode = udev_device_get_devnode(device);if (devnode)drives.push_back(devnode);udev_device_unref(device);}udev_enumerate_unref(enumerate);}udev_unref(udev_context);return drives;
}/*** 检查光驱是否可用*/
bool GetValidDrive(std::string& drive)
{if (!drive.empty()){int fd = open(drive.c_str(), O_RDONLY | O_NONBLOCK);if (fd != -1){if (ioctl(fd, CDROM_GET_CAPABILITY, 0) == -1){close(fd);return false; }close(fd);return true;}else{return false;}}else{return false;}
}
3.使用libcdio库获取光驱数量
#include <cdio/cdio.h>
#include <cdio/cd_types.h>
#include <cdio/logging.h>//打印日志
static void log_handler(cdio_log_level_t level, const char message[])
{switch(level) {case CDIO_LOG_DEBUG:case CDIO_LOG_INFO:return;default:printf("cdio %d message: %s\n", level, message);}
}int main(int argc, const char *argv[])
{char **ppsz_cd_drives=NULL, **c;//设置日志的回调函数cdio_log_set_handler(log_handler);//打印设备的CD驱动ppsz_cd_drives = cdio_get_devices(DRIVER_DEVICE);if (NULL != ppsz_cd_drives) for( c = ppsz_cd_drives; *c != NULL; c++ ) {printf("-- Drive: %s\n", *c);}//释放CD驱动cdio_free_device_list(ppsz_cd_drives);ppsz_cd_drives = NULL;printf("-----\n");return 0;
}
向光驱中写文件
通过命令行向光驱中写文件
# -Z 向选中的设备中烧入一个初始的session
# -M 添加一个新的Session, 选项来避免关闭会话,从而在后续操作中保持会话打开
# -dvd-compat 提供对DVD-ROM的最大兼容性
# -speed=N 指定光驱的刻录速度
# -R: 用于支持 UNIX 文件系统的长文件名和权限
# -J: 用于支持 Windows 文件系统的长文件名。# 初始化写入
growisofs -Z /dev/sr1 -R -J /home/users/file1 /home/users/file2
# 追加写入
growisofs -M /dev/sr1 -R -J /home/users/file3
通过libburn命令写入文件
#include <iostream>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#include "libburn/libburn.h"using namespace burn;
using namespace std;void burn_iso_to_disc(struct burn_drive *drive, char *iso_path)
{struct burn_source *data_src = NULL, *fifo_src = NULL;struct burn_disc *target_disc = NULL;struct burn_session *session = NULL;struct burn_write_opts *burn_options = NULL;enum burn_disc_status disc_state;struct burn_track *track;struct burn_progress progress;int fd = 0;off_t fixed_size;int fifo_chunksize = 2048;int fifo_chunks = 2048;int padding = 300 * 1024; //a padding of 300 kiB helps to avoid the read-ahead bugchar reasons[BURN_REASONS_LEN];struct stat stbuf;time_t start_time;target_disc = burn_disc_create();session = burn_session_create();burn_disc_add_session(target_disc, session, BURN_POS_END);track = burn_track_create();burn_track_define_data(track, 0, padding, 1, BURN_MODE1);//打开需要写入的数据fd = open(iso_path, O_RDONLY);if (fd >= 0)if (fstat(fd, &stbuf) != -1)if ((stbuf.st_mode & S_IFMT) == S_IFREG)fixed_size = stbuf.st_size;else{cout << "error to open filedescriptor\n"<< endl;return;}//转换文件为可写入的文件对象data_src = burn_fd_source_new(fd, -1, fixed_size);if (data_src == NULL){cout << "Could not open data source " << iso_path << endl;return;}//安装fifo对象到数据源对象中fifo_src = burn_fifo_source_new(data_src, fifo_chunksize, fifo_chunks, 0);if (fifo_src == NULL){cout << "Could not create fifo object of 4 MB\n"<< iso_path << endl;return;}if (burn_track_set_source(track, fifo_src) != BURN_SOURCE_OK){cout << "Cannot attach source object to track object\n";return;}burn_session_add_track(session, track, BURN_POS_END);burn_source_free(data_src);//检测驱动的状态disc_state = burn_disc_get_status(drive);if (disc_state != BURN_DISC_BLANK && disc_state != BURN_DISC_APPENDABLE){return;}//创建烧写配置burn_options = burn_write_opts_new(drive);burn_write_opts_set_perform_opc(burn_options, 0); burn_write_opts_set_multi(burn_options, 0);burn_write_opts_set_simulate(burn_options, 0);burn_write_opts_set_underrun_proof(burn_options, 1);if (burn_write_opts_auto_write_type(burn_options, target_disc, reasons, 0) == BURN_WRITE_NONE){cout << "FATAL: Failed to find a suitable write mode with this media.\n"<< "Reasons given:" << endl<< reasons << endl;return;}burn_drive_set_speed(drive, 0, 0);burn_set_signal_handling((void*)"libburner : ", NULL, 0x30);cout << "Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n";burn_disc_write(burn_options, target_disc);while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)usleep(100002);while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE){int size, free_bytes, ret;char *status_text;ret = burn_fifo_inquire_status(fifo_src, &size, &free_bytes, &status_text);if(ret > 0)cout << "fifo " << status_text << " %% " << 100 - (100.0*free_bytes/size) << " fill" << endl;sleep(1);}//释放缓存burn_write_opts_free(burn_options);burn_source_free(fifo_src);burn_track_free(track);burn_disc_free(target_disc);
}int main(int argc, char const *argv[])
{struct burn_drive_info *drive_list;unsigned int drive_count = 0;int ret;//初始化if (!burn_initialize()){cout << "init burn drive failed" << endl;return -1;}//检测光驱while(!burn_drive_scan(&drive_list, &drive_count));usleep(100002);if(drive_count <=0){cout << "error to scan drive" << endl;return -1;}//捕获光驱ret = burn_drive_grab(drive_list[0].drive, 1);if(!ret){cout << "error to grab the drive";return -1;}//写文件burn_iso_to_disc(drive_list[0].drive, "myiso.iso");//释放光驱burn_drive_release(drive_list[0].drive, 1);burn_finish();return 0;
}
相关文章:

通过C++程序实现光驱的自动化刻录和读取
文章目录 ISO文件格式光盘的基本概念光盘种类特点DVDR光盘使用windows调用Linux调用Linux平台下用到的C库:读取设备驱动列表向光驱中写文件 数字存储媒体快速发展的今天,光驱的使用已经不像以前那样普及了。但是在数据备份、安装软件和操作系统、旧设备兼容等领域还…...

【电商项目实战】商品详情显示与Redis存储购物车信息
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《电商项目实战》。🎯🎯 &am…...
概率论基础
1.概率论 1.1 随机事件与概率 1.1.1 基本概念 样本点(sample point): 称为试验 S S S的可能结果为样本点,用 ω \omega ω表示。 样本空间(sample space):称试验 S S S的样本点构成的集合为样本空间,用 Ω \Omega Ω表示…...
Mac电脑CMake安装和配置
1.从CMake官网下载dmg文件并且安装 ...
FormData传送复杂数据
FormData 是一个用于创建表单数据对象的 JavaScript 类。它通常用于通过 JavaScript 发送表单数据,尤其是用于发送 AJAX 请求时非常有用。 使用 FormData 可以方便地构建一个以 multipart/form-data 格式提交的表单数据,这允许你在发送 XMLHttpRequest …...

力扣回溯算法-电话号码的字母组合
力扣第17题,电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 .电话号码的字母组合 示例: 输入:“2…...
运维面试笔试题
目录 shell脚本 nginx 数据库mysql k8s(kubernetes) 安全与防护 网络TCP/IP shell脚本 1 通过正则表达式匹配文本...

Oracle database 静默安装 oracle12c 一键安装 12.1.0.2
基于oracle安装包中应答文件实现一键安装 注意此安装脚本基于12.1.0.2 安装包 原始安装包结构为两个压缩包 此脚本使用安装包为原始压缩包解压后、 重新封装为一个.zip压缩包 建议在linux 环境下解压重新压缩后 使用该脚本 支持环境: Linux :centerOS 7 oracle :12.1.0.…...

【Java EE初阶三 】线程的状态与安全(上)
1. join方法与多线程 1.1 初识多线程 为了提高cpu得利用率,因此就引入了多个线程的概念;即每个线程负责完成整个程序的一部分工作即可。 写一个代码,让主线程,创建一个新的线程,由新线程负责完成运算(12。…...
英飞凌TC3xx之一起认识GTM系列(五)如何实现GTM与DSADC关联的配置
英飞凌TC3xx之一起认识GTM系列(五)如何实现GTM与DSADC关联的配置 1 GTM与DSADC的连接1.1 EDSADC 到 GTM 的连接1.1.1 工作原理说明1.1.2 应用举例1.2 GTM 到 EDSADC 的连接1.2.1 工作原理说明1.2.2 应用举例2 总结编者按:笔者在从事这部分开发工作的时候,看着手册上的各种通…...

小兔鲜儿 uniapp - 购物车模块
目录 加入购物车 接口相关 购物车列表 静态结构 登录状态 列表渲染 删除购物车 接口相关 参考代码 修改商品信息 接口相关 修改商品数量 修改商品选中/全选 底部结算信息 计算总钱数(总金额) 带返回按钮的购物车 完成加入购物车…...
Python使用PyMySql增删改查Mysql数据库
PyMysql简介 PyMysql是Python中用于连接MySQL数据库的一个第三方库,它实现了MySQL客户端/服务器协议,使得Python程序能够与MySQL服务器进行交互。由于Python 2的mysql-python(又称mysqldb)模块在Python 3上支持不够完善࿰…...

前端实现websocket类封装
随着Web应用程序的发展,越来越多的人开始利用Websocket技术来构建实时应用程序。Websocket是一种在客户端和服务器之间建立持久连接的协议。这种协议可以在一个单独的连接上实现双向通信。与HTTP请求-响应模型不同,Websocket允许服务器自主地向客户端发送…...

鸿蒙开发中的一些小问题
这是我在学习鸿蒙开发中遇见的小问题 Q1:This custom component must have a build function. <etsLint>Q2:page_title is not translated into en_US(American English)Q3:Module "../CustomComponent/CustomButton" declar…...

OpenCV-12绘制图像
OpenCV提供了许多绘制图像的API,可以在图像上绘制各种图形,例如直线,矩形,圆,椭圆等图形。 一、画直线 利用API line(img, pt1, pt2, color, thickness, lineType, shift)可以绘制直线。 其中…...

“2023年的技术发展与个人成长:回顾与展望“
文章目录 每日一句正能量前言工作生活未来展望后记 每日一句正能量 凡事顺其自然,遇事处于泰然,得意之时淡然,失意之时坦然,艰辛曲折必然,历尽沧桑悟然。 前言 在这快速发展的信息时代,技术的进步和创新不…...

算法逆袭之路(1)
11.29 开始跟进算法题进度! 每天刷4题左右 ,一周之内一定要是统一类型 而且一定稍作总结, 了解他们的内在思路究竟是怎样的!! 12.24 一定要每天早中晚都要复习一下 早中午每段一两道, 而且一定要是同一个类型, 不然刷起来都没有意义 12.26/27: 斐波那契数 爬…...
2023.12.31每日一题
LeetCode每日一题 2023年的最后一题 1154.一年中的第几天 1154. 一年中的第几天 - 力扣(LeetCode) 描述 给你一个字符串 date ,按 YYYY-MM-DD 格式表示一个 现行公元纪年法 日期。返回该日期是当年的第几天。 示例 1: 输入&a…...
Flink实时电商数仓(八)
用户域登录各窗口汇总表 主要任务:从kafka页面日志主题读取数据,统计 七日回流用户:之前活跃的用户,有一段时间不活跃了,之后又开始活跃,称为回流用户当日独立用户数:同一个用户当天重复登录&a…...
Python Pymysql实现数据存储
什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2 中则使用mysqldb。 PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。 PyMySQL 安装 在使用 PyMySQL 之前…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...