From 0ab8e423de33e5cc6716ff911aa7488178cd06f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?weizhenfeng=E9=9F=A6=E6=8C=AF=E5=87=A4?= Date: Mon, 2 Jun 2025 22:16:34 +0800 Subject: [PATCH] =?UTF-8?q?feat(decorator-pattern):=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E8=BE=93=E5=85=A5=E6=B5=81=E7=9A=84=E7=BC=93?= =?UTF-8?q?=E5=86=B2=E8=A3=85=E9=A5=B0=E5=99=A8-=20=E6=96=B0=E5=A2=9E=20My?= =?UTF-8?q?FileInputStreamBuffer=20=E7=B1=BB=EF=BC=8C=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E6=96=87=E4=BB=B6=E8=BE=93=E5=85=A5=E6=B5=81?= =?UTF-8?q?=20-=20=E5=88=9B=E5=BB=BA=20App=20=E7=B1=BB=EF=BC=8C=E6=BC=94?= =?UTF-8?q?=E7=A4=BA=E4=BD=BF=E7=94=A8=E7=BC=93=E5=86=B2=E8=A3=85=E9=A5=B0?= =?UTF-8?q?=E5=99=A8=E8=AF=BB=E5=8F=96=E6=96=87=E4=BB=B6=E7=9A=84=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E6=8F=90=E5=8D=87-=20=E6=B7=BB=E5=8A=A0=20.gitignore?= =?UTF-8?q?=20=E6=96=87=E4=BB=B6=EF=BC=8C=E5=BF=BD=E7=95=A5=20IDE=20?= =?UTF-8?q?=E5=92=8C=E6=9E=84=E5=BB=BA=E5=B7=A5=E5=85=B7=E7=9A=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6-=20=E5=88=9B=E5=BB=BA=20Maven=20?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=20pom.xm?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 38 +++++++++ pom.xml | 17 ++++ src/main/java/decorator_pattern/app/App.java | 58 +++++++++++++ .../tech/MyFileInputStreamBuffer.java | 85 +++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 .gitignore create mode 100644 pom.xml create mode 100644 src/main/java/decorator_pattern/app/App.java create mode 100644 src/main/java/decorator_pattern/tech/MyFileInputStreamBuffer.java 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); + } +}