如何用Jackson CsvMapper序列化Java类并生成CSV数据的SHA-256
解决方案
核心思路是先把CSV数据写入内存流(ByteArrayOutputStream)获取字节数组,用这个数组计算SHA-256,再将字节数组写入目标文件,确保哈希计算的内容和最终写入文件的内容完全一致。
修改后的完整代码如下:
import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.HexFormat; public class CsvUtils { public static <T> String writeToCsvFileWithHeaderAndSha256( List<T> listOfData, Path absolutePathToFile, Class<T> clazz, char columnSeparator) throws IOException, NoSuchAlgorithmException { CsvMapper mapper = new CsvMapper(); // 复用CSV配置Schema,保证格式和原方法完全一致 CsvSchema schema = mapper.schemaFor(clazz) .withColumnSeparator(columnSeparator) .withoutQuoteChar() .withHeader(); // 1. 将数据写入内存流,获取CSV字节数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (var writer = mapper.writerWithSchemaFor(clazz) .with(schema) .writeValues(new OutputStreamWriter(baos, StandardCharsets.UTF_8))) { writer.writeAll(listOfData); } byte[] csvBytes = baos.toByteArray(); // 2. 计算SHA-256哈希 MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hashBytes = digest.digest(csvBytes); String sha256Hex = HexFormat.of().formatHex(hashBytes); // 3. 将CSV字节数组写入目标文件 Files.write(absolutePathToFile, csvBytes); return sha256Hex; } }
关键说明:
- 复用Schema:把原方法中的CSV配置(分隔符、表头、无引号)提取为独立的
CsvSchema对象,避免两次序列化的格式差异导致哈希和文件内容不匹配。 - 显式指定编码:写入内存流时明确使用
UTF-8编码,和Jackson默认写入文件的编码保持一致,防止因编码不同生成不同的字节数组。 - 内存流中转:先通过内存流拿到完整的CSV字节数据,再同步完成哈希计算和文件写入,确保哈希对应的内容和最终文件完全一致。
内容的提问来源于stack exchange,提问作者armaka
相关产品推荐
相关产品推荐

