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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ixiangfeng 金牌黑马   /  2014-2-26 13:01  /  1386 人查看  /  13 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ixiangfeng 于 2014-2-26 13:02 编辑
  1. /*
  2. 练习:上传图片:从客户端上传一张图片到服务端,服务端返回“上传成功”信息
  3. 注意结束标记,否则会使程序一直等待,因为阻塞式方法读取不到信息
  4. 就会一直等待

  5. 客户端:
  6. 1.建立服务端点
  7. 2.读取客户端已有的图片数据
  8. 3.通过socket输出流将数据发送给服务端
  9. 4.读取服务端反馈信息
  10. 5.关闭资源

  11. 服务端:
  12. 1.建立服务端点
  13. 2.获取Socket对象
  14. 3.从Socket对象的读取流中获取图片信息
  15. 4.把图片写到硬盘中(复制)
  16. 5.返回反馈信息
  17. 6.关闭资源

  18. */
  19. import java.io.*;
  20. import java.net.*;

  21. class Client //客户端
  22. {
  23.         public static void main(String [] args)throws Exception
  24.         {
  25.                 //客户端关联本地一图片,写入到流中
  26.                 Socket s = new Socket("172.18.174.15", 1111);
  27.                 BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("1.JPG"));
  28.                 BufferedOutputStream bufos = new BufferedOutputStream(s.getOutputStream());

  29.                 int len = 0;
  30.                 byte [] buf = new byte[1024];
  31.                 while ((len = bufis.read(buf)) != -1)
  32.                 {
  33.                         bufos.write(buf, 0, len);
  34.                 }
  35.                 s.shutdownOutput();

  36.                
  37.                 BufferedInputStream bufis2 = new BufferedInputStream(s.getInputStream());
  38.                 byte [] bufIn = new byte[1024];
  39.                 int num = bufis2.read(bufIn);
  40.                 System.out.println(new String(bufIn, 0, num));

  41.                 s.close();
  42.                 bufis.close();
  43.                 bufos.close();        
  44.                 bufis2.close();
  45.         }
  46. }



  47. class Server //服务端
  48. {
  49.         public static void main(String [] args)throws Exception
  50.         {
  51.                 //读取客户端上传的图片,并复制保存一份,返回反馈信息
  52.                 ServerSocket ss =new ServerSocket(1111);
  53.                 Socket s = ss.accept();

  54.                 BufferedInputStream bufis = new BufferedInputStream(s.getInputStream());
  55.                 BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("12.JPG"));

  56.                 int len = 0;
  57.                 byte [] buf = new byte [1024];
  58.                 while ((len = bufis.read(buf)) != -1)
  59.                 {
  60.                         bufos.write(buf, 0, len);
  61.                 }
  62.                 s.shutdownInput();

  63.                 BufferedOutputStream bufos2 = new BufferedOutputStream(s.getOutputStream());               
  64.                 bufos2.write("上传成功".getBytes());
  65.                
  66.                 bufos2.close();               
  67.                 s.close();
  68.                 ss.close();
  69.                 bufis.close();
  70.                 bufos.close();
  71.         }
  72. }
复制代码

请问下这个程序哪里有问题?上传的时候总是不完整的

评分

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

查看全部评分

13 个回复

倒序浏览
我测试了下,没问题啊
回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:23
我测试了下,没问题啊

有运行吗?我总是缺少几个字节的 像毕老师那样不用高效方法就不会有问题
回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:23
我测试了下,没问题啊

还是用了Buffered高效的就不能再用自定义的数组缓冲区? 这个好像没有这个说法的啊 有点不明白
回复 使用道具 举报
换了个大的图片试了下,的确有问题,图片的最后一部分没有传完整
回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:33
换了个大的图片试了下,的确有问题,图片的最后一部分没有传完整

是啊 如果不使用Buffer方法,只使用自定义数组作缓冲区是没问题的 不知道问题出在哪里 两者同时用就会出现复制不完整的 但是使用Buffer也是可以读入到数组中去的 好郁闷
回复 使用道具 举报
qqwwdr 中级黑马 2014-2-26 13:38:06
7#
加入了 flush();
没有问题了,客户端和服务器端都要加

  1.   while ((len = bufis.read(buf)) != -1)
  2.                     {
  3.                             bufos.write(buf, 0, len);
  4.                                                         bufos.flush();
  5.                     }
复制代码

评分

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

查看全部评分

回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:38
加入了 flush();
没有问题了,客户端和服务器端都要加

字节流也要刷新缓冲区的吗? 怎么记得老毕说字节流不用刷新缓冲区的?
回复 使用道具 举报
qqwwdr 中级黑马 2014-2-26 13:44:55
9#
ixiangfeng 发表于 2014-2-26 13:40
字节流也要刷新缓冲区的吗? 怎么记得老毕说字节流不用刷新缓冲区的?

我也感觉字节流不用刷,一般我也没有刷,但是刷了这个问题就解决了,
可能是只要涉及到  缓冲流 都属要 刷新吧
回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:44
我也感觉字节流不用刷,一般我也没有刷,但是刷了这个问题就解决了,
可能是只要涉及到  缓冲流 都属要  ...

嗯嗯  记得老毕一直都有强调字节流不用刷新,可能一般人也不会像我这样用吧 因为其实Buffered里面其实就是用数组作缓冲区的了 像我这样用了Buffered还用自定义缓冲区的人应该很少 可能是跟我自定义的数组缓冲区有关 老毕说的不用刷新应该是直接用Buffered的情况 因为我使用了Buffered但是把数据存到了自定义缓冲区中所以才需要刷新吧 现在想想好像是这个原理了 PS:非常感谢
回复 使用道具 举报
ixiangfeng 发表于 2014-2-26 13:49
嗯嗯  记得老毕一直都有强调字节流不用刷新,可能一般人也不会像我这样用吧 因为其实Buffered里面其实就 ...

你分析得有道理,学习了,其实我也没怎么想明白这个问题,呵呵
回复 使用道具 举报
qqwwdr 发表于 2014-2-26 13:53
你分析得有道理,学习了,其实我也没怎么想明白这个问题,呵呵

好像还是有点问题 如果我不用数组 只是用BufferedOutputStream去写的话也是需要刷新的,但是我看之前写的代码和老毕说的都是不用刷新的、、、好郁闷啊
回复 使用道具 举报
ixiangfeng 发表于 2014-2-26 14:10
好像还是有点问题 如果我不用数组 只是用BufferedOutputStream去写的话也是需要刷新的,但是我看之前写的 ...

老毕的IO流的视频我都没怎么看,IO流翻过来覆过去的多西太多了,感觉实际中也就只用到一般的几个模板代码,你碰到的这个问题我记下 了,可能还是   只要缓冲流都flush下,安全一点。
原理的话可能要去翻 jdk的源码才能知道了。网上我也没有搜到相关的问题
回复 使用道具 举报
这个问题我也遇到过,后来我就把数组大小定义成1M(1024*1024)就没问题了,定义成1M是没有问题的,毕竟我们处理的是图片,这个已经足够了,我的感觉是定义数组长度不够。你试着打开那个少了几个字节的图片就会发现图片尾部失真了,但我也找不出原因。希望能和你提一下我的感觉和做法,你试一下可不可以把。也有可能是jdk版本的问题导致的,估计要看一下源码才知道事情的真相。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马