// Resize every PNG in a directory, keeping EXIF data
File[] images = FileUtil.ls("/photos");
for (File img : images)
ImgUtil.scale(img, FileUtil.file("/thumbnails", img.getName()), 0.5f);
// New in v39: Preserves orientation using ImageMetadataReader
core EnhancementsNetUtil.ipToLong(), longToIp() (no more manual bit ops).ZipUtil.zipStream() for streaming large archives.ImageUtil.resize() with better algorithms (Lanczos, etc.).StrUtil.subBetween() now returns null (instead of empty string) when the delimiters aren’t found. This aligns with “absent” semantics. A quick grep of your codebase will catch any affected calls.
// Run every Monday at 9 AM with virtual thread executor
CronUtil.schedule("0 0 9 ? * MON", "reportJob", () ->
try (var exec = ThreadUtil.newVirtualExecutor())
exec.submit(() -> generateDailyReport());
);
CronUtil.setMatchSecond(true);
CronUtil.start();