Java 之 实现C++库函数等价函数遇到的问题

背景

项目中之前使用到的库大部分是C++编写的,后面因业务需要,要求把部分库用java实现,期间遇到一些问题,这里记录下

问题

写入字符数组类型时,数组大小不同问题

java 复制代码
 //C++源代码
 char fileName_[100];
 fwrite(fileName_, sizeof(fileName_), 1, pf);
// 问题:因该写入100字节,但是写入时发现只按照实际大小写入
//java 修改后的方法
 this.fileName = new byte[100]; // 固定大小为100字节
 //这里是入参
 byte[] nameBytes = fileName.getBytes(StandardCharsets.UTF_8);
 //这句是关键,这样再写入时,就是100字节了
 System.arraycopy(nameBytes, 0, this.fileName, 0, Math.min(nameBytes.length, this.fileName.length));

写入整数类型时,遇到大小端问题

C++‌:其数据在内存中的存储顺序(字节序)‌直接依赖于底层CPU架构和编译器的实现‌。例如,在x86架构上,C++程序默认使用小端模式存储数据,而在PowerPC等架构上则可能使用大端模式。因此,C++开发者需要关注并处理跨平台或跨系统通信时的字节序转换问题。

Java‌:其设计目标是"一次编写,到处运行",因此‌在语言层面统一规定使用大端(Big-Endian)字节序‌,也称为网络字节序。Java虚拟机(JVM)负责屏蔽底层硬件差异,对所有基本数据类型(如int、float)的存储和网络传输都采用大端模式,开发者通常无需关心底层硬件的字节序。

java 复制代码
//java中按小端写入整数
private static void writeLittleInt(RandomAccessFile fos, int value) {
    try {
        // 分配4字节缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(4);
        // 设置为小端序
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        // 将整数写入缓冲区
        buffer.putInt(value);
        // 写入文件
        fos.write(buffer.array());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

日志记录

如果不想依赖第三方日志库,可以直接使用jdk提供的java.util.logging

java 复制代码
import java.util.logging.*;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 日志记录器
 */
private static final Logger logger = Logger.getLogger(TestLib.class.getName());
static {
    try {
        // 日志文件名称
        String logFileName = "mylib.log";
        // 使用项目根目录下的 logs 文件夹
        String projectRoot = new File("").getAbsolutePath();
        String logDirPath = projectRoot + File.separator + "logs";
        Path logDir = Paths.get(logDirPath);
        if (!logDir.toFile().exists()){
            // 确保目录存在
            Files.createDirectories(logDir);
        }
        // true表示追加模式
        FileHandler fileHandler = new FileHandler(logDirPath + File.separator + logFileName, true);
        fileHandler.setFormatter(new Formatter() {
            @Override
            public String format(LogRecord record) {
                return String.format("[%s] %s: %s%n",
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(record.getMillis())),
                        record.getLevel(),
                        record.getMessage());
            }
        });
        // 添加到当前类的 logger
        logger.addHandler(fileHandler);
        logger.setLevel(Level.INFO);
        logger.setUseParentHandlers(false);

        // 可选:也添加到根日志记录器
        Logger rootLogger = Logger.getLogger("");
        rootLogger.addHandler(fileHandler);

        logger.info("Log file initialization successful: log file: " + logFileName);

    } catch (Exception e) {
        System.err.println("Log file init failed: " + e.getMessage());
    }
}

这样,当你调用logger.info函数写日志时,当前程序目录下的logs/mylib.log文件就有内容了。

总结

这里没有涉及到整个结构体的序列化写入,只是基础类型的操作。

相关推荐
毕设源码-郭学长1 小时前
【开题答辩全过程】以 基于java的停车管理系统的设计与实为例,包含答辩的问题和答案
java·开发语言
MaoziShan1 小时前
CMU Subword Modeling | 09 Lexemes, or What Dictionaries Know about Morphology
开发语言·人工智能·机器学习·语言模型·自然语言处理·c#
流云细水2 小时前
Spec实战:需求编辑与需求评审
java·人工智能
柴郡猫乐园2 小时前
JDK中一个单例模式的实现
java·开发语言·单例模式
星空彼岸0072 小时前
SA-Token在SpringBoot中的实战指南
java·spring boot·后端
闻哥2 小时前
ConcurrentHashMap 1.7 源码深度解析:分段锁的设计与实现
java·开发语言·jvm·spring boot·面试·jdk·hash
Ivanqhz2 小时前
半格与数据流分析的五个要素(D、V、F、I、Λ)
开发语言·c++·后端·算法·rust
liann1192 小时前
4.3.2_WEB——WEB后端语言——PHP
开发语言·前端·网络·安全·web安全·网络安全·php
元让_vincent2 小时前
DailyCoding C++ | SLAM里的“幽灵数据”:从一个未初始化的四元数谈C++类设计
开发语言·c++·slam·构造函数·类设计·激光里程计