A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 我要的幸福呢 于 2014-2-17 21:17 编辑

问题已明白,看了一下源码,BufferedOutputStream里面缓冲区(也就是一个字节数组)的默认大小是8192字节,当缓冲区中数据达到最大值后就是自动执行flush()操作,将数据刷新出去。我代码的问题就是数据到最后并没有填满BufferedOutputStream的缓冲区,所以没有自动刷新出去,也没有手动刷新(包括bufOut的关闭操作),所以造成了数据丢失。

看过了tcp上传图片的视频之后,自己写的代码,使用了缓冲流(视频中毕老师没用缓冲流),发现了数据丢失的情况,即原图片大小为18999字节,上传后图片大小只有16384字节。经过多次尝试之后,发现加入下面注释的代码之后正常,但是我记得缓冲字节输出流是不用flush刷新的,翻看io流时候的代码也没有。大家帮忙看看问题出在哪里。代码如下
  1. import java.io.*;
  2. import java.net.*;

  3. class UploadPicClient
  4. {
  5.         public static void main(String[] args) throws Exception
  6.         {
  7.                 Socket s = new Socket("192.168.31.1",10010);

  8.                 BufferedInputStream bis = new BufferedInputStream(
  9.                         new FileInputStream("client.png"));
  10.                 BufferedOutputStream bufOut = new BufferedOutputStream(
  11.                         s.getOutputStream());

  12.                 byte[] buf = new byte[1024];
  13.                 int len = 0;
  14.                 while((len=bis.read(buf))!=-1)
  15.                 {
  16.                         bufOut.write(buf,0,len);
  17.                         //bufOut.flush();//为什么不刷新,就不正常?
  18.                 }
  19.                 s.shutdownOutput();

  20.                 BufferedReader bufIn = new BufferedReader(
  21.                         new InputStreamReader(s.getInputStream()));
  22.                 System.out.println(bufIn.readLine());

  23.                 bis.close();
  24.                 s.close();

  25.         }
  26. }

  27. class UploadPicServer
  28. {
  29.         public static void main(String[] args) throws Exception
  30.         {
  31.                 ServerSocket ss = new ServerSocket(10010);
  32.                 Socket s = ss.accept();

  33.                 String ip = s.getInetAddress().getHostAddress();
  34.                 System.out.println(ip+" connected...");

  35.                 BufferedInputStream bufIn = new BufferedInputStream(
  36.                         s.getInputStream());
  37.                 BufferedOutputStream bos = new BufferedOutputStream(
  38.                         new FileOutputStream("server.png"));

  39.                 byte[] buf = new byte[1024];
  40.                 int len = 0;
  41.                 while((len=bufIn.read(buf))!=-1)
  42.                 {
  43.                         bos.write(buf,0,len);
  44.                 }

  45.                 PrintWriter pw = new PrintWriter(s.getOutputStream(),true);
  46.                 pw.println("图片上传成功");

  47.                 bos.close();
  48.                 s.close();
  49.                 ss.close();
  50.         }
  51. }
复制代码



评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

4 个回复

正序浏览
本帖最后由 joure 于 2014-2-18 14:52 编辑
e.c 发表于 2014-2-17 15:51
bufos.close()关闭流的时候会将缓冲数据写入。

正解!,如果LZ将代码中有 bufOut.close()关闭流的动作,不刷新也是可以的
但是你只写了一个 bufOut.flush(),没有close();
毕老师的视频中没有刷新,但是有一个close的动作
io流使用完后一定要记得关闭资源,要养成习惯!
不释放资源可能会导致内存泄露

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

回复 使用道具 举报
我要的幸福呢 发表于 2014-2-17 07:48
不是吧,下面是讲利用字节流缓冲区复制MP3文件的视频截图

bufos.close()关闭流的时候会将缓冲数据写入。
回复 使用道具 举报
程澄 发表于 2014-2-17 01:26
你记错了,只要用到缓冲区就必须刷新流

不是吧,下面是讲利用字节流缓冲区复制MP3文件的视频截图

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

回复 使用道具 举报
你记错了,只要用到缓冲区就必须刷新流
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马