通过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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/582824.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PiflowX大数据流水线系统

PiflowX大数据流水线系统。支持分布式计算引擎flink和spark。以所见即所得的方式&#xff0c;实现大数据采集、处理、存储与分析流程化配置、运行与智能监控。 PiflowX基于Piflow&#xff08;PiFlow: 混合型科学大数据流水线系统&#xff0c;包含丰富的处理器组件&#xff0c;…

算法导论复习(七) 动态规划

动态规划一般用来求解最优化问题 设计一个动态规划算法一般有以下四步&#xff1a; 描述一个最优解的结构特征。递归地定义最优解的值。计算最优解的值&#xff0c;通常采用自底向上的方法。利用计算出的信息构造出一个最优解。 钢条切割问题 体现了动态规划的一个重要性质&a…

k8s 网络

还没有部署网络。 k8s的网络类型&#xff1a; k8s中的通信模式&#xff1a; 1&#xff0c;pod内部之间容器和容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间。可以直接通信的。 2&#xff0c;同一个node节点之内不同pod之间的通信。…

大创项目推荐 深度学习YOLO抽烟行为检测 - python opencv

文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习YOLO抽烟行为检测 该项目较为新颖&#xff0c;适合作为竞赛课…

BAQ压缩MATLAB仿真

本专栏目录: ​​​​​​​全球SAR卫星大盘点与回波数据处理专栏目录-CSDN博客 我们按照上一期文章的BAQ原理编写MATLAB代码,进行baq压缩与解压缩的全流程验证,并分析BAQ压缩对信号指标造成的影响。 生成3个点目标回波数据,加入高斯噪声,对回波进行BAQ压缩和解BAQ压缩,…

具有出色的数据速率、SI8642BA-AUR、SI8642BB-AS1R、SI8641BB-B-IUR、SI8635BD-B-ISR低功耗数字隔离器

一、简介 Si86xx 超低功耗数字隔离器系列是CMOS器件&#xff0c;与传统隔离技术相比&#xff0c;具有出色的数据速率、传播延迟、功耗、尺寸、可靠性和外部BOM优势。这些产品的工作参数在宽温度范围内和整个设备使用寿命内保持稳定&#xff0c;便于设计和高度统一的性能。所有…

java毕业设计—基于SpringBoot的小米商城的设计与实现

1&#xff0c;绪论 1.1 背景调研 电子商城的建设&#xff0c;不仅仅是初级网上购物的实现&#xff0c;它能够有效地在Internet上构架安全的和易于扩展的业务框架体系&#xff0c;实现BToB&#xff08;企业对企业&#xff09;、BToC&#xff08;企业对用户&#xff09;以及CTo…

首次使用TypeScript,报错:无法重新声明块级范围变量(声明变量报错)

前几天在书写TypeScript代码时&#xff0c;出现了声明变量报错的情况&#xff0c;具体情况如下&#xff1a; let arr: number; arr 10; console.log(arr);报错如下&#xff1a; 解决方案&#xff1a; 在配置文件tsconfig.json中&#xff0c;配置如下代码&#xff1a; { &q…

【计算机毕业设计】SSM医疗药品采购系统

项目介绍 ssm医疗药品采购系统。主要功能有&#xff1a; 用户管理&#xff1a;管理员列表&#xff1b; 采购管理&#xff1a;采购列表&#xff1b; 药品出库&#xff1a;药品出库&#xff1b; 库存管理&#xff1a;库存统计&#xff1b; 数据维护&#xff1a;药品列表、仓库…

软件测试常见的面试题,这些题面试前看提高百分之60的通过率

01、您所熟悉的测试用例设计方法都有哪些&#xff1f;请分别以具体的例子来说明这些方法在测试用例设计工作中的应用。 答&#xff1a;有黑盒和白盒两种测试种类&#xff0c;黑盒有等价类划分法&#xff0c;边界分析法&#xff0c;因果图法和错误猜测法。白盒有逻辑覆盖法&…

3D手势光流计算

GitHub - NVIDIA/flownet2-pytorch: Pytorch implementation of FlowNet 2.0: Evolution of Optical Flow Estimation with Deep Networks 计算光流 conda create -n 3dgesture python3.8 conda activate 3dgesture ​pip install torch 1. import torch时报错ModuleNotFoun…

从 Linux Crontab 到 K8s CronJob,定时任务正在经历怎样的变革

作者&#xff1a;黄晓萌(学仁) 背景 Job 表示短周期的作业&#xff0c;定时 Job 表示按照预定的时间运行Job&#xff0c;或者按照某一频率周期性的运行 Job。比如&#xff1a; 许多传统企业使用 Linux 自带的 crontab 来做定时任务的方案&#xff0c;该方案非常简单&#xff…

腾讯云服务器购买流程:一步步全流程购买指南

腾讯云服务器购买流程直接在官方秒杀活动上购买比较划算&#xff0c;在云服务器CVM或轻量应用服务器页面自定义购买价格比较贵&#xff0c;但是自定义购买云服务器CPU内存带宽配置选择范围广&#xff0c;活动上购买只能选择固定的活动机&#xff0c;选择范围窄&#xff0c;但是…

Vue 问题解决

一、问题&#xff1a;TypeError: (0 , _message.default) is not a function 当没有default时,在其他页面import引入的时&#xff0c;必须加{}。 二、问题&#xff1a;Vue前端页面的表格数据总是一行一行的显示 使用Async/Await来解决前端数据一行一行显示的问题。可以将获取部…

鸿蒙原生应用再添新丁!搜狐集团、航旅纵横入局鸿蒙

鸿蒙原生应用再添新丁&#xff01;搜狐集团、航旅纵横入局鸿蒙 来自 HarmonyOS 微博12月28日消息&#xff0c;搜狐集团宣布与华为达成全面合作&#xff01;搜狐新闻近期将完成#鸿蒙原生应用#核心功能版本&#xff0c;搜狐视频也启动了#鸿蒙原生应用#开发&#xff01;这不仅是一…

数据结构学习 Leetcode494 目标和

关键词&#xff1a;动态规划 01背包 dfs回溯 一个套路&#xff1a; 01背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要逆序遍历完全背包&#xff1a;空间优化之后dp【target1】&#xff0c;遍历的时候要正序遍历 题目&#xff1a; 解法一&#xff1a; …

k8s搭建(三、k8s从节点创建)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

Frappe Charts:数据可视化的强大工具

一、产品简介&#xff1a; 一个简单、零依赖、响应式的 开源SVG 图表库。这个图表库无论是数据更新还是屏幕大小变化&#xff0c;都能快速响应并更新图表。数据生成和悬停查看都有舒服的交互动效&#xff0c;体验感很好。不仅支持配置颜色&#xff0c;外观定制也很方便。还支持…

操作教程|MeterSphere UI测试+VNC:简单、快捷地查看UI测试实时执行详情

编者注&#xff1a;本文为CSDN博主hxe116的原创文章。 原文链接为&#xff1a;https://blog.csdn.net/hxe116/article/details/134714960?spm1001.2014.3001.5502 作为一款一站式的开源持续测试平台&#xff0c;MeterSphere涵盖了测试跟踪、接口测试、UI测试和性能测试等功能…

centos下docker安装Rocketmq总结,以及如何更换mq端口

默认你已经装好了docker哈 安装docker-compose sudo curl -L https://github.com/docker/compose/releases/download/1.25.1-rc1/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-composechmod x /usr/local/bin/docker-composedocker-compose --version成功打印…