java 输出流转换成输入流_在JAVA中如何将输出流转为输入流的类的实现
问题背景
在实际应用中,我们会碰的一个功能的输出的字节流,是另一个功能输入字节流的情况。一般情况下,我们可以使用ByteArrayOutputStream和ByteArrayInputStream实现相应的功能。
来看下面的测试代码:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
public class ByteArrayTest {
public static void main(String[] argv) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
PrintWriter ps = new PrintWriter(output);
for (int i = 0; i < 1000; i++) {
ps.printf("This is line %d\n", i);
}
ps.close();
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
byte[] buffer = new byte[1024];
int len = 0;
while ((len = input.read(buffer)) > 0) {
System.out.write(buffer, 0, len);
}
input.close();
}
}
在上面的代码中,我们通过ByteArrayOutputStream对象把输出转换为字节数组,在通过ByteArrayInputStream对象把字节数组转换为输入流。
当需要转换的字节流比较小时,上面的方法是一个简便的且行之有效的方法,然而当字符流比较大时,上面的代码会消耗大量的内存,甚至可能出现内存溢出的情况。
解决方法
为解决上一节提出的问题,本文实现一个字节流转换类,可以直接使用完成以上功能。基本原理是开辟一个缓冲区,通过对缓冲区并发的交互的读写操作实现内存复用和字节流的转换。
转换类代码如下:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class InputOutputTransferStream extends InputStream {
private byte[] buffer = new byte[4096];
private int byteLength = 0;
private boolean writeOver = false;
private boolean readOver = false;
private InputOutputStream outputStream = new InputOutputStream();
private Object lock = new Object();
public class InputOutputStream extends OutputStream {
@Override
public void write(int c) throws IOException {
synchronized(lock) {
if (byteLength < 0)
return;
while (byteLength >= buffer.length) {
try {
lock.wait();
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
if (byteLength < buffer.length) {
buffer[byteLength] = (byte)c;
byteLength++;
}
lock.notify();
}
}
@Override
public void write(byte[] buf, int offset, int len) throws IOException {
synchronized(lock) {
if (readOver)
return;
while (len > 0) {
if (byteLength >= buffer.length) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
int nLeft = buffer.length - byteLength;
int nLen = Math.min(nLeft, len);
try {
System.arraycopy(buf, offset, buffer, byteLength, nLen);
} catch (Exception ex) {
}
offset += nLen;
len -= nLen;
byteLength += nLen;
lock.notify();
}
}
}
@Override
public void write(byte[] buffer) throws IOException {
write(buffer, 0, buffer.length);
}
public void close() {
synchronized(lock) {
//byteLength = -1;
writeOver = true;
lock.notify();
}
}
}
public OutputStream getOutputStream() {
return outputStream;
}
@Override
public int read() throws IOException {
synchronized(lock) {
if (readOver)
return -1;
while (byteLength == 0) {
if (writeOver) {
throw new IOException("closed");
}
try {
lock.wait();
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
if (byteLength < 0) {
return -1;
} else {
int nResult = buffer[0];
for (int i = 0; i < byteLength-1; i++) {
buffer[i] = buffer[i+1];
}
byteLength -= 1;
lock.notify();
return nResult;
}
}
}
@Override
public int read(byte[] buf, int offset, int len) throws IOException {
synchronized(lock) {
if (readOver)
return -1;
while (byteLength == 0) {
if (writeOver)
return -1;
try {
lock.wait();
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
if (byteLength < 0) {
System.out.println("read -1");
return -1;
} else {
int nLen = Math.min(byteLength, len);
System.arraycopy(buffer, 0, buf, offset, nLen);
for (int i = 0; i < byteLength-nLen; i++) {
buffer[i] = buffer[i+nLen];
}
byteLength -= nLen;
lock.notify();
return nLen;
}
}
}
@Override
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
@Override
public void close() {
synchronized(lock) {
readOver = true;
//byteLength = -1;
lock.notify();
}
}
}
使用方法和测试
以下代码即可用于测试,也为该转换类使用方法的样例:
import java.io.IOException;
import java.io.PrintWriter;
public class InputOutputStreamTest {
public static void main(String[] argv) throws IOException {
final InputOutputTransferStream input = new InputOutputTransferStream();
final PrintWriter ps = new PrintWriter(input.getOutputStream());
new Thread() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
ps.printf("This is line %d\n", i);
}
ps.close();
try {
input.getOutputStream().close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = input.read(buffer)) >= 0) {
System.out.write(buffer, 0, len);
}
input.close();
}
}
运行该代码,与原始代码实现的结果相同,执行结果均为:
This is line 0
This is line 1
This is line 2
This is line 3
This is line 4
……
This is line 995
This is line 996
This is line 997
This is line 998
This is line 999
java 输出流转换成输入流_在JAVA中如何将输出流转为输入流的类的实现相关推荐
- java小数转换成分数_如何将小数转换为分数?
我需要将小数转换为分数.转换成10英尺很容易. 1.5 => 15/10 这可以通过以下代码完成: public class Rational { private int num, denom; ...
- java怎么把毫秒转换成天数_关于java:如何将毫秒转换为“ hh:mm:ss”格式?
我糊涂了. 绊倒这个线程后,我试图找出如何格式化具有hh:mm:ss格式的倒数计时器. 这是我的尝试- //hh:mm:ss String.format("%02d:%02d:%02d&qu ...
- java英里转换成千米_公里和英里的换算?
展开全部 公里636f70793231313335323631343130323136353331333431346331和英里的换算: 1 英里 = 1.609344公里 英里是一种英制计量单位,在 ...
- java字符串拆分成数组_用Java实现JVM第八章《数组和字符串》
小傅哥 | https://bugstack.cn 沉淀.分享.成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获.目前已完成的专题有:Netty4.x实战专题案例.用J ...
- java小数转换成百分数_在java中如何把小数转化成百分数
import java.text.NumberFormat; public class Test { //在java中如何把小数转化成百分数 public static void main(Strin ...
- java父类转换成子类_【转】java 父类与子类的转换
最近同事调的一个服务报错,查看后是日期之间转换出的问题.代码里是把 java.sql.Date 类型的对象 强制转换为 java.sql.Timestamp 类型的对象.报java.lang.Clas ...
- java英里转换成千米_英里和公里怎么换算
展开全部 1 英里 =1.609344公里 具体过程: 1 英里 =5 280 英尺 = 63 360 英寸 = 1 609.344 米 = 1760 码 = 1.609344千 米=1.609344 ...
- java json转换xml格式_在Java中将JSON对象转换为XML格式?
JSON是一种轻量级的数据交换格式,并且JSON的格式类似于键值对.我们可以使用org.json.XML类将JSONObject转换为XML格式,这提供了将XML文本转换为JSONObject并将JS ...
- myeclipse将普通java项目转换成maven项目_Myeclipse Java项目转换成Maven项目
CentOS7安装iptables防火墙 CentOS7默认的防火墙不是iptables,而是firewalle. 安装iptable iptable-service #先检查是否安装了iptable ...
- 将已有项目转为se项目_如何将 Java 项目转换成 Maven 项目
本文内容 Java 项目 Maven 项目 Java 项目转换成 Maven 项目 本文主要介绍如何将 Java 项目转换成 Maven 项目.首先要明确的是,用 Maven 管理 Java 项目的确 ...
最新文章
- silverlight数据库应用程序开发
- 为了在元宇宙里摸到东西,扎克伯格整出了一款新电子皮肤,成本6美元
- ***一般如何***服务器
- 按频率对元素进行排序
- 加速度计和陀螺仪数据融合
- python字符子串_子字符串和子序列(Python),子串,python
- liunx 下mysql 的安装
- 【图像去噪】基于matlab GUI均值+中值+高斯低通+多种小波变换图像去噪【含Matlab源码 856期】
- howler 音频插件使用
- Windows中的用户和组以及用户密码处理
- 经典C语言编程100例——题目+答案代码(完结)
- steam加速_玩转steam的新姿势:必备加速器推荐!
- python-回调函数
- TwinCAT3 EL6070-1648授权模块使用
- PHP + 小程序开发过程
- bash+vasp+vaspkit能量应变计算弹性常数
- COOKIE与SESSION比较
- 计算机中SQL中文,SQL是什么意思 sql的中文含义
- 联想服务器CPU系列,联想推出采用第三代英特尔至强处理器的ThinkSystem SR860 V2服务器...
- jquery 获取上传图片的大小
热门文章
- shift键计算机功能,shift键的功能
- jupyter notebook 用PPT展示代码 +插入图片
- 【转】Linux那些事儿 之 戏说USB(23)设备的生命线(二)
- BLAG: Improving the Accuracy of Blacklists
- 在WIN2003安装TD8,问题汇总
- 计算机中xp系统中qq文件,WinXP电脑QQ为什么登不上去?如何解决?
- 关于用scala 写Elasticsearch +springboot+jpa
- 使用u盘前需要将其格式化怎么办?
- SpaceX将在菲律宾推出星链服务
- 线程的共享资源与独立资源