java实现刻录机刻录功能(dom4j+imapi)Windows版

本文详细介绍了如何使用Java和com4j库调用IMAPI接口来控制本地刻录机,包括环境设置、步骤详解、关键类的生成和刻录代码示例。重点在于解决32位兼容问题和自定义类的创建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景和实现原理

        最近公司项目要求通过java控制本地刻录机,在网上查了很多资料都没有说的很详细的,之后参考了一篇博客https://stackoverflow.com/questions/8556291/reading-and-writing-to-a-dvd-cd-java,最终通过dom4j调用本机imapi实现了刻录功能,在此记录一下。

        该实现方式就是通过com4j类库进行桥接,com4j是一个类型安全的java/com桥接器,作为一个java类库,允许java与Microsoft组件对象模型无缝的互操作,在此不做过多的赘述,

详细请参考:【笔记】Java 调用 COM 组件之 com4j 使用说明 - 子兮子兮

主要原理:通过com4j将对应的imapi2.dll,imapi2fs.dll接口生成java可以调用的类。

二、实现步骤

步骤1:将jdk版本切换为32位(重要),原因是imapi2.dll,imapi2fs.dll是32位的应用程序,无法与64位jdk进行匹配,否则生成的类无法使用,会报以下错误

Exception in thread "main" com4j.ExecutionException: com4j.ComException: 80040154 CoCreateInstance failed : Class not registered : .\com4j.cpp:153

步骤2:com4j包下载(两个都需下载)

1)com4j对应jar包(用于桥接应用程序)

        下载地址:https://github.com/kohsuke/com4j/downloads

2)com4j对应maven包

<dependency>
   <groupId>org.jvnet.com4j</groupId>
   <artifactId>com4j</artifactId>
   <version>2.1</version>
</dependency>

步骤3:解压下载后的文件,将文件中jar包(tlbimp.jar、com4j.jar、args4j-2.0.1.jar)复制到某一文件夹下,如(D:\bb)

步骤4:cmd到D:\bb目录,执行

java -jar tlbimp.jar -o imapi2fs -p com.yxm.burn.imapi2 "C:\Windows\System32\imapi2fs.dll"
java -jar tlbimp.jar -o imapi2 -p com.yxm.burn.imapi2 "C:\Windows\System32\imapi2.dll"

步骤5: 将imapi2和imapi2fs下的类进行整合

其中ClassFactoryExt、IDiscFormat2DataExt、StreamClassFactory需要自己补充

package com.yxm.imapi2;

import com4j.COM4J;

/**
 * Defines methods to create COM objects
 */
public abstract class ClassFactoryExt {
    private ClassFactoryExt() {} // instanciation is not allowed

    /**
     * Microsoft IMAPIv2 Data Writer
     */
    public static com.yxm.imapi2.IDiscFormat2DataExt createMsftDiscFormat2Data() {
        return COM4J.createInstance( com.yxm.imapi2.IDiscFormat2DataExt.class, "{2735412A-7F64-5B0F-8F00-5D77AFBE261E}" );
    }
}
package com.yxm.imapi2;

import com4j.IID;
import com4j.VTID;

/**
 * Data Writer
 */
@IID("{27354153-9F64-5B0F-8F00-5D77AFBE261E}")
public interface IDiscFormat2DataExt extends com.yxm.imapi2.IDiscFormat2Data {
    /**
     * The state (usability) of the current media
     */
    @VTID(18)
    //com.ms.imapi2.IMAPI_FORMAT2_DATA_MEDIA_STATE currentMediaStatus();
    int currentMediaStatusExt();
}
package com.yxm.imapi2;

import com4j.COM4J;

/**
 * Defines methods to create COM objects
 */
public abstract class StreamClassFactory {
    private StreamClassFactory() {} // instanciation is not allowed


    /**
     * Boot options
     */
    public static com.yxm.imapi2.IBootOptions createBootOptions() {
        return COM4J.createInstance( com.yxm.imapi2.IBootOptions.class, "{2C941FCE-975B-59BE-A960-9A2A262853A5}" );
    }

    /**
     * File system image
     */
    public static com.yxm.imapi2.IFileSystemImage3 createMsftFileSystemImage() {
        return COM4J.createInstance( com.yxm.imapi2.IFileSystemImage3.class, "{2C941FC5-975B-59BE-A960-9A2A262853A5}" );
    }

    /**
     * Microsoft IMAPIv2 Iso Image Manager
     */
    public static com.yxm.imapi2.IIsoImageManager createMsftIsoImageManager() {
        return COM4J.createInstance( com.yxm.imapi2.IIsoImageManager.class, "{CEEE3B62-8F56-4056-869B-EF16917E3EFC}" );
    }
}

步骤6:编写调用本地刻录光驱代码(对应的iso文件可自己去创建生成)

package com.yxm.burn;

import com.yxm.imapi2.*;

import java.io.File;

public class TestUtils {
    public static void main(String[] args) {
        testBurn();
    }

    public static void testBurn(){
        File isoFile = new File("D:\\tmp\\4e1c1bf3-1195-4513-847a-c55d11500d60.iso");

        //创建IMAPIv2光盘驱动
        IDiscMaster2 dm = ClassFactory.createMsftDiscMaster2();
        //获取可用光盘驱动的个数
        int count = dm.count();

        //获取其中一个光盘驱动(建议只链接一个光盘驱动)
        String recorderUniqueId = null;
        for (int i = 0; i < count; i++)
        {
            String cur = dm.item(i);
            recorderUniqueId = cur;
        }
        //创建刻录机
        IDiscRecorder2 recorder = ClassFactory.createMsftDiscRecorder2();
        //初始化刻录机
        recorder.initializeDiscRecorder(recorderUniqueId);
        //        log.info("正在使用的刻录机: " + recorder.vendorId() + " " + recorder.productId());

        //创建镜像管理器
        IIsoImageManager imageManager = StreamClassFactory.createMsftIsoImageManager();
        imageManager.setPath(isoFile.getAbsolutePath());
        imageManager.validate();
        //        log.info("ISO验证成功: " + isoFile.getAbsolutePath());

        //创建数据写入程序
        IDiscFormat2DataExt discData = ClassFactoryExt.createMsftDiscFormat2Data();
        //数据写入程序链接刻录机
        discData.recorder(recorder);
        //客户端名称(用于确定刻录机保留冲突)
        discData.clientName(TestUtils.class.getSimpleName());
        //获取当前刻录文件状态(确保文件是iso文件)
        int mediaStatus = discData.currentMediaStatusExt();
        //        log.info("刻录文件的状态: " + mediaStatus);
        if ((mediaStatus & IMAPI_FORMAT2_DATA_MEDIA_STATE.IMAPI_FORMAT2_DATA_MEDIA_STATE_WRITE_PROTECTED.comEnumValue()) != 0)
            throw new RuntimeException("Media is write protected / not empty.");

        //检查写入程序的写入内容是否为空
        int addr = discData.nextWritableAddress();
        if (addr != 0)
            throw new RuntimeException("Disc is not empty, not writing.");
        //获取iso文件流
        IStream isoStream = imageManager.stream();

        //开始刻录
        //        log.info("Writing CD");
        discData.write(isoStream);

    }
}

三、总结

        通过以上步骤即可实现java调用本地刻录光驱进行刻录,再配合自动生成iso文件即可实现将对应的文件或文件夹自动刻录到光盘,iso文件的生成可以使用UltraISO软件,通过命令进行调用,

Process exec = Runtime.getRuntime().exec("cmd.exe /c c: && cd c:/UltraISO && ultraiso -lowercase -imax -file " + filePath + " -output " + trgPath);

 以上就可以实现刻录机的调用控制。

注意:

1、imapi2包中的类一定要自己手动生成,因为每个电脑的应用程序的对应注册表中的值是不一样的,直接复用可能会无法实现接口调用。

2、如果将此功能作为插件部署(即通过java -jar  xxxx.jar运行项目)需要将步骤4对应生成的com4j-amd64.dll或com4j-x86.dll放到C:\Windows\System32文件夹中,否则无法使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值