commit 0ab8e423de33e5cc6716ff911aa7488178cd06f2 Author: weizhenfeng韦振凤 Date: Mon Jun 2 22:16:34 2025 +0800 feat(decorator-pattern): 实现文件输入流的缓冲装饰器- 新增 MyFileInputStreamBuffer 类,用于缓冲文件输入流 - 创建 App 类,演示使用缓冲装饰器读取文件的性能提升- 添加 .gitignore 文件,忽略 IDE 和构建工具的配置文件- 创建 Maven 项目配置文件 pom.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0122714 --- /dev/null +++ b/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + feng.yu + shengsheng_study + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + diff --git a/src/main/java/decorator_pattern/app/App.java b/src/main/java/decorator_pattern/app/App.java new file mode 100644 index 0000000..e500662 --- /dev/null +++ b/src/main/java/decorator_pattern/app/App.java @@ -0,0 +1,58 @@ +package decorator_pattern.app; + +import decorator_pattern.tech.MyFileInputStreamBuffer; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.file.Files; +import java.time.Instant; + +/** + * @author weizhenfeng韦振凤 + * @version 1.0 + * @description: TODO + * @date 2025/6/2 下午9:51 + */ +public class App { + + public static void main(String[] args) { + unOpt(); + + opt(); + + } + + private static void opt() { + File file = new File("F:\\BigData\\交易模型\\交易模型-存款交易信息.xlsx"); + long startTime = Instant.now().toEpochMilli(); + + try ( + InputStream fis = Files.newInputStream(file.toPath()); + InputStream bufferedStream = new MyFileInputStreamBuffer(fis) // 使用缓冲装饰器 + ) { + while (bufferedStream.read() != -1) { + // 空循环 + } + System.out.println("缓冲读取耗时(ms): " + (Instant.now().toEpochMilli() - startTime)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void unOpt() { + File file = new File("F:\\BigData\\交易模型\\交易模型-存款交易信息.xlsx"); + long epochMilli = Instant.now().toEpochMilli(); + try (FileInputStream fileInputStream = new FileInputStream(file)) { + while (fileInputStream.read() != -1) { + if (fileInputStream.read() == -1) { + break; + } + } + System.out.println(Instant.now().toEpochMilli() - epochMilli); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/decorator_pattern/tech/MyFileInputStreamBuffer.java b/src/main/java/decorator_pattern/tech/MyFileInputStreamBuffer.java new file mode 100644 index 0000000..8f70602 --- /dev/null +++ b/src/main/java/decorator_pattern/tech/MyFileInputStreamBuffer.java @@ -0,0 +1,85 @@ +package decorator_pattern.tech; + +import java.io.IOException; +import java.io.InputStream; + +public class MyFileInputStreamBuffer extends InputStream { + + private final InputStream decoratedInputStream; // 被装饰的InputStream + private final byte[] buffer = new byte[8192]; // 缓冲区 + private int position; // 当前缓冲区位置 + private int count; // 缓冲区有效字节数 + + // 使用InputStream而不是具体FileInputStream,提高通用性 + public MyFileInputStreamBuffer(InputStream inputStream) { + this.decoratedInputStream = inputStream; + } + + @Override + public int read() throws IOException { + // 缓冲区为空时填充 + if (position >= count) { + if (!fillBuffer()) { + return -1; // 流结束 + } + } + // 从缓冲区读取一个字节 + return buffer[position++] & 0xFF; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int totalRead = 0; + while (len > 0) { + // 缓冲区为空则填充 + if (position >= count) { + if (!fillBuffer()) { + return totalRead == 0 ? -1 : totalRead; + } + } + + // 计算本次可读取的字节数 + int available = count - position; + int toRead = Math.min(available, len); + + // 从缓冲区复制数据 + System.arraycopy(buffer, position, b, off, toRead); + + // 更新位置和长度 + position += toRead; + off += toRead; + len -= toRead; + totalRead += toRead; + } + return totalRead; + } + + private boolean fillBuffer() throws IOException { + position = 0; + count = decoratedInputStream.read(buffer); + return count > 0; + } + + @Override + public void close() throws IOException { + decoratedInputStream.close(); // 委托给被装饰对象 + position = count = 0; // 重置缓冲区状态 + } + + // 可选:重写其它方法提升性能 + @Override + public long skip(long n) throws IOException { + if (n <= 0) return 0; + + // 先使用缓冲区中的可用数据 + int availableInBuffer = count - position; + if (availableInBuffer >= n) { + position += (int)n; + return n; + } + + // 需要跳过超过缓冲区的内容 + position = count; // 消耗掉当前缓冲区 + return availableInBuffer + decoratedInputStream.skip(n - availableInBuffer); + } +}