问题背景

在实际应用中,我们会碰的一个功能的输出的字节流,是另一个功能输入字节流的情况。一般情况下,我们可以使用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中如何将输出流转为输入流的类的实现相关推荐

  1. java小数转换成分数_如何将小数转换为分数?

    我需要将小数转换为分数.转换成10英尺很容易. 1.5 => 15/10 这可以通过以下代码完成: public class Rational { private int num, denom; ...

  2. java怎么把毫秒转换成天数_关于java:如何将毫秒转换为“ hh:mm:ss”格式?

    我糊涂了. 绊倒这个线程后,我试图找出如何格式化具有hh:mm:ss格式的倒数计时器. 这是我的尝试- //hh:mm:ss String.format("%02d:%02d:%02d&qu ...

  3. java英里转换成千米_公里和英里的换算?

    展开全部 公里636f70793231313335323631343130323136353331333431346331和英里的换算: 1 英里 = 1.609344公里 英里是一种英制计量单位,在 ...

  4. java字符串拆分成数组_用Java实现JVM第八章《数组和字符串》

    小傅哥 | https://bugstack.cn 沉淀.分享.成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获.目前已完成的专题有:Netty4.x实战专题案例.用J ...

  5. java小数转换成百分数_在java中如何把小数转化成百分数

    import java.text.NumberFormat; public class Test { //在java中如何把小数转化成百分数 public static void main(Strin ...

  6. java父类转换成子类_【转】java 父类与子类的转换

    最近同事调的一个服务报错,查看后是日期之间转换出的问题.代码里是把 java.sql.Date 类型的对象 强制转换为 java.sql.Timestamp 类型的对象.报java.lang.Clas ...

  7. java英里转换成千米_英里和公里怎么换算

    展开全部 1 英里 =1.609344公里 具体过程: 1 英里 =5 280 英尺 = 63 360 英寸 = 1 609.344 米 = 1760 码 = 1.609344千 米=1.609344 ...

  8. java json转换xml格式_在Java中将JSON对象转换为XML格式?

    JSON是一种轻量级的数据交换格式,并且JSON的格式类似于键值对.我们可以使用org.json.XML类将JSONObject转换为XML格式,这提供了将XML文本转换为JSONObject并将JS ...

  9. myeclipse将普通java项目转换成maven项目_Myeclipse Java项目转换成Maven项目

    CentOS7安装iptables防火墙 CentOS7默认的防火墙不是iptables,而是firewalle. 安装iptable iptable-service #先检查是否安装了iptable ...

  10. 将已有项目转为se项目_如何将 Java 项目转换成 Maven 项目

    本文内容 Java 项目 Maven 项目 Java 项目转换成 Maven 项目 本文主要介绍如何将 Java 项目转换成 Maven 项目.首先要明确的是,用 Maven 管理 Java 项目的确 ...

最新文章

  1. silverlight数据库应用程序开发
  2. 为了在元宇宙里摸到东西,扎克伯格整出了一款新电子皮肤,成本6美元
  3. ***一般如何***服务器
  4. 按频率对元素进行排序
  5. 加速度计和陀螺仪数据融合
  6. python字符子串_子字符串和子序列(Python),子串,python
  7. liunx 下mysql 的安装
  8. 【图像去噪】基于matlab GUI均值+中值+高斯低通+多种小波变换图像去噪【含Matlab源码 856期】
  9. howler 音频插件使用
  10. Windows中的用户和组以及用户密码处理
  11. 经典C语言编程100例——题目+答案代码(完结)
  12. steam加速_玩转steam的新姿势:必备加速器推荐!
  13. python-回调函数
  14. TwinCAT3 EL6070-1648授权模块使用
  15. PHP + 小程序开发过程
  16. bash+vasp+vaspkit能量应变计算弹性常数
  17. COOKIE与SESSION比较
  18. 计算机中SQL中文,SQL是什么意思 sql的中文含义
  19. 联想服务器CPU系列,联想推出采用第三代英特尔至强处理器的ThinkSystem SR860 V2服务器...
  20. jquery 获取上传图片的大小

热门文章

  1. shift键计算机功能,shift键的功能
  2. jupyter notebook 用PPT展示代码 +插入图片
  3. 【转】Linux那些事儿 之 戏说USB(23)设备的生命线(二)
  4. BLAG: Improving the Accuracy of Blacklists
  5. 在WIN2003安装TD8,问题汇总
  6. 计算机中xp系统中qq文件,WinXP电脑QQ为什么登不上去?如何解决?
  7. 关于用scala 写Elasticsearch +springboot+jpa
  8. 使用u盘前需要将其格式化怎么办?
  9. SpaceX将在菲律宾推出星链服务
  10. 线程的共享资源与独立资源