首先请查看一下JavaAPI,可以看到InputStream读取流有三个方法,分别为read(),read(byte[] b),read(byte[] b, int off, int len)。其中read()方法是一次读取一个字节,鬼都知道效率是非常低的。所以最好是使用后面两个方法。

例如以下代码:

Java代码  
  1. /**
  2. * 读取流
  3. *
  4. * @param inStream
  5. * @return 字节数组
  6. * @throws Exception
  7. */
  8. public static byte[] readStream(InputStream inStream) throws Exception {
  9. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  10. byte[] buffer = new byte[1024];
  11. int len = -1;
  12. while ((len = inStream.read(buffer)) != -1) {
  13. outSteam.write(buffer, 0, len);
  14. }
  15. outSteam.close();
  16. inStream.close();
  17. return outSteam.toByteArray();
  18. }

我们来测试一下:

Java代码  
  1. public static void main(String[] args) {
  2. try {
  3. File file = new File("C:\\ceshi.txt");
  4. FileInputStream fin = new FileInputStream(file);
  5. byte[] filebt = readStream(fin);
  6. System.out.println(filebt.length);
  7. } catch (Exception e) {
  8. e.printStackTrace();
  9. }
  10. }

后台会打印这个文本的字节大小。看起来,这个是没有问题的。

关于InputStream类的available()方法
这个方法的意思是返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。为什么需要这个方法?因为在一些网络应用中,数据流并不是一次性就能传递的,如果我们还是像上面那样去将这个流转换,会出问题的。我们来做一个例子,这是一个Socket编程的简单例子,具体Socket内容我会在后面文章中解释的。

首先编写两个类,一个用户初始化Socket服务,并且处理每个请求都有新的线程去处理,代码如下:

Java代码  
  1. package com.service;
  2. import java.net.*;
  3. public class DstService {
  4. public static void main(String[] args) {
  5. try {
  6. // 启动监听端口 8001
  7. ServerSocket ss = new ServerSocket(8001);
  8. boolean bRunning = true;
  9. while (bRunning) {
  10. // 接收请求
  11. Socket s = ss.accept();
  12. // 将请求指定一个线程去执行
  13. new Thread(new DstServiceImpl(s)).start();
  14. }
  15. } catch (Exception e) {
  16. e.printStackTrace();
  17. }
  18. }
  19. }

那么处理类我们也来看一下:

Java代码  
  1. package com.service;
  2. import java.io.*;
  3. import java.net.*;
  4. import com.util.*;
  5. public class DstServiceImpl implements Runnable {
  6. Socket socket = null;
  7. public DstServiceImpl(Socket s) {
  8. this.socket = s;
  9. }
  10. public void run() {
  11. try {
  12. InputStream ips = socket.getInputStream();
  13. OutputStream ops = socket.getOutputStream();
  14. while (true) {
  15. byte[] bt = StreamTool.readStream(ips);
  16. String str = new String(bt);
  17. System.out.println("主机收到信息:" + str);
  18. String restr = "你好,主机已经收到信息!";
  19. ops.write(restr.getBytes());
  20. ops.flush();
  21. }
  22. } catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

至于工具类,我就直接给代码了:

Java代码  
  1. package com.util;
  2. import java.io.*;
  3. public class StreamTool {
  4. public static void main(String[] args) {
  5. try {
  6. File file = new File("C:\\ceshi.txt");
  7. FileInputStream fin = new FileInputStream(file);
  8. byte[] filebt = readStream(fin);
  9. System.out.println(filebt.length);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. /**
  15. * @功能 读取流
  16. * @param inStream
  17. * @return 字节数组
  18. * @throws Exception
  19. */
  20. public static byte[] readStream(InputStream inStream) throws Exception {
  21. ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
  22. byte[] buffer = new byte[1024];
  23. int len = -1;
  24. while ((len = inStream.read(buffer)) != -1) {
  25. outSteam.write(buffer, 0, len);
  26. }
  27. outSteam.close();
  28. inStream.close();
  29. return outSteam.toByteArray();
  30. }
  31. }

你可以直接运行这个类,会看到流被转换的效果。

我们来写一个Socket客户端测试一下:

Java代码  
  1. package com.client;
  2. import java.io.*;
  3. import java.net.*;
  4. import com.util.*;
  5. public class DstClient {
  6. public static void main(String[] args) {
  7. try {
  8. Socket socket = new Socket("127.0.0.1", 8001);
  9. // 开启保持活动状态的套接字
  10. socket.setKeepAlive(true);
  11. // 设置读取超时时间
  12. socket.setSoTimeout(30 * 1000);
  13. OutputStream ops = socket.getOutputStream();
  14. String mess = "你好,我是崔素强!";
  15. ops.write(mess.getBytes());
  16. InputStream ips = socket.getInputStream();
  17. byte[] rebyte = StreamTool.readStream(ips);
  18. String remess = new String(rebyte);
  19. System.out.println("收到主机消息:" + remess);
  20. socket.close();
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. }
  24. }
  25. }

先运行DstService,然后运行客户端,看效果。会发现,控制台没有任何输出。经过调试发现,因为请求死在了

Java代码  
  1. while ((len = inStream.read(buffer)) != -1) {

这行代码上面。这就是在网络应用中会造成的后果。那么如何解决呢?有的人给出了如下代码:

Java代码  
  1. int count = in.available();
  2. byte[] b = new byte[count];
  3. in.read(b);

可是在进行网络操作时往往出错,因为你调用available()方法时,对发发送的数据可能还没有到达,你得到的count是0。需要做如下修改,是我们的读取流方法改成如下:

Java代码  
  1. /**
  2. * @功能 读取流
  3. * @param inStream
  4. * @return 字节数组
  5. * @throws Exception
  6. */
  7. public static byte[] readStream(InputStream inStream) throws Exception {
  8. int count = 0;
  9. while (count == 0) {
  10. count = inStream.available();
  11. }
  12. byte[] b = new byte[count];
  13. inStream.read(b);
  14. return b;
  15. }

下面你在运行,会看到服务端和客户端都收到了消息。

关于InputStream.read(byte[] b)和InputStream.read(byte[] b,int off,int len)这两个方法都是用来从流里读取多个字节的,有经验的程序员就会发现,这两个方法经常 读取不到自己想要读取的个数的字节。比如第一个方法,程序员往往希望程序能读取到b.length个字节,而实际情况是,系统往往读取不了这么多。仔细阅读Java的API说明就发现了,这个方法 并不保证能读取这么多个字节,它只能保证最多读取这么多个字节(最少1个)。因此,如果要让程序读取count个字节,最好用以下代码:

Java代码  
  1. int count = 100;
  2. byte[] b = new byte[count];
  3. int readCount = 0; // 已经成功读取的字节的个数
  4. while (readCount < count) {
  5. readCount += inStream.read(b, readCount, count - readCount);
  6. }

这样就能保证读取100个字节,除非中途遇到IO异常或者到了数据流的结尾情况!

转载于:https://www.cnblogs.com/songtzu/archive/2013/05/06/3063127.html

java InputStream读取数据问题【转http://cuisuqiang.iteye.com/blog/1434416】相关推荐

  1. java InputStream读取数据问题【转】http://cuisuqiang.iteye.com/blog/1434416

    首先请查看一下JavaAPI,可以看到InputStream读取流有三个方法,分别为read(),read(byte[] b),read(byte[] b, int off, int len).其中r ...

  2. 【转载】java InputStream读取数据问题

    原文链接:http://www.cnblogs.com/MyFavorite/archive/2010/10/19/1855758.html 1. 关于InputStream.read()      ...

  3. inputstream读取html乱码,java InputStream 读取汉语言内容的解决乱码

    java InputStream 读取中文内容的解决乱码 String suffix=file.substring(file.lastIndexOf('.')+1,file.length()); if ...

  4. java怎么读取数据?

    Java属于入门容易,天花板却极高的编程语言.java怎么读取数据?对于java工程师来说技术的不断发展,需要不断学习java进阶知识.为了帮助大家巩固基础,本文解答了java怎么读取数据?等相关问题 ...

  5. java获取inputstream_java InputStream读取数据问题

    1. 关于InputStream.read() 在从数据流里读取数据时,为图简单,经常用InputStream.read()方法.这个方法是从流里每次只读取读取一个字节,效率会非常低.     更好的 ...

  6. InputStream读取数据

    InputStream读取流有三个方法: read() read(byte[] b) read(byte[] b, int off, int len) 在从数据流里读取数据时,为图简单,经常用Inpu ...

  7. java dataset读取数据,TensorFlow读写数据

    前言 回顾前面: 众所周知,要训练出一个模型,首先我们得有数据.我们第一个例子中,直接使用dataset的api去加载mnist的数据.(minst的数据要么我们是提前下载好,放在对应的目录上,要么就 ...

  8. java acr122 读取数据_使用ACR122U 从NTAG203Chip 读取数据

    1.使用NFC Pro(Android APK)读取的TAG信息: 2.连接ACR 122U之后,从设备管理处可以看出ACR122U采用标准的微软CCID和PC/SC驱动(USB CCID): 3.P ...

  9. java 分段读取数据_java _io_ .read()分段读取字节

    java _io_ .read()分段读取字节 发布时间:2020-05-06 11:22:43 来源:51CTO 阅读:256 作者:wx5d21d5e6e5ab1 byte[] flush =ne ...

最新文章

  1. 设置硬盘休眠linux,linux笔记本设置休眠
  2. 使用一些可选的将字符串配置属性转换为其他类型
  3. 800万行代码的鸿蒙系统,在世界上处于什么水平?
  4. 7个开源的TTS(文本转语音)系统
  5. html空格暂停,关于audio标签暂停的问题
  6. Java开发笔记(一百二十八)Swing的图标
  7. Ubuntu下安装osu
  8. 汇编程序debug的使用完整使用
  9. 【算法精解】计数排序
  10. Word文档多级标题自动编号设置
  11. 还在一节一节数链条吗?使用SOLIDWORKS参数化设计自动计算链条节数
  12. winpe加载raid_WinPE安装RAID卡驱动的详细教程
  13. 用Java实现图像识别_只需要这三步,用Java也能图片识别
  14. [team]开发中的“最速曲线”
  15. “三年拿下全球第一!”7年小米销量冲到全球第二,雷军做对了什么?
  16. 图解SQL面试题:经典30题,数据分析人求职必考,强烈推荐收藏
  17. Actor编程模型——简介
  18. hdu1348 Wall
  19. 案例分析:session丢失及appdomain回收
  20. python-数据库-4

热门文章

  1. 线性表ArrayList和LinkedList源码详解。
  2. java -IO流_字符流
  3. bzoj 1441: Min 裴蜀定理
  4. 第二周作业-停车场门禁控制系统的状态机
  5. 给RadioButtonList这些加JS事件
  6. Android开发之ViewPager结合Fragment实现滑动页面的效果(源代码分享)
  7. Android开发之自定义Notification(源代码分享)
  8. Spring 定时任务之 @Scheduled cron表达式
  9. Android Stadio 导入moudle 不显示
  10. Android自定义流式布局-FlowLayout