feat(decorator-pattern): 实现文件输入流的缓冲装饰器- 新增 MyFileInputStreamBuffer 类,用于缓冲文件输入流

- 创建 App 类,演示使用缓冲装饰器读取文件的性能提升- 添加 .gitignore 文件,忽略 IDE 和构建工具的配置文件- 创建 Maven 项目配置文件 pom.xml
This commit is contained in:
weizhenfeng韦振凤 2025-06-02 22:16:34 +08:00
commit 0ab8e423de
4 changed files with 198 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@ -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

17
pom.xml Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>feng.yu</groupId>
<artifactId>shengsheng_study</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -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();
}
}
}

View File

@ -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);
}
}