解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個(gè)文件無(wú)法傳輸多個(gè)問(wèn)題
被一個(gè)朋友問(wèn)到一個(gè)關(guān)于sokcet文件傳輸?shù)膯?wèn)題
他發(fā)現(xiàn)他寫(xiě)的代碼只能發(fā)送一次文件,沒(méi)辦法發(fā)送第二次,或者說(shuō)發(fā)送第二次的時(shí)候服務(wù)端就接收不到了。
部分代碼
// 開(kāi)始接收文件 byte[] bytes = new byte[1024]; //byte[] bytes = new byte[dis.available()]; int length = 0; while((length = dis.read(bytes, 0, bytes.length)) != -1) { System.out.println(bytes.length); fos.write(bytes, 0, length); fos.flush(); } System.out.println("======== 文件接收成功 [File Name:" + fileName + "] [Size:" + getFormatFileSize(fileLength) + "] ========");
我給他調(diào)試的時(shí)候發(fā)現(xiàn)確確實(shí)實(shí)發(fā)送第一次文件后就就一直阻塞在while循環(huán)里了,出不來(lái)。
本來(lái)傳輸完第一次的文件后應(yīng)該有打印“======== 文件接收成功 [File。。。。。。”
這些信息,但是實(shí)際上沒(méi)有,而且也不報(bào)錯(cuò)。
調(diào)試的時(shí)候打斷點(diǎn)也是走著走著斷點(diǎn)就不見(jiàn)了,要說(shuō)他是阻塞也不像是阻塞,因?yàn)槿绻亲枞脑捚鸫a斷點(diǎn)是會(huì)存在的只是無(wú)法往下運(yùn)行了而已,但是他這個(gè)調(diào)試就是直接斷點(diǎn)就消失了,我也懵了。
后來(lái)查資料才發(fā)現(xiàn)原來(lái)只要客戶端的DataOutputStream不close掉,那么服務(wù)端的DataInputStream read就永遠(yuǎn)不等于-1。
即使文件的數(shù)據(jù)已經(jīng)傳完了,DataInputStream依舊會(huì)等著客戶端DataOutputStream再傳數(shù)據(jù)過(guò)來(lái)。
最后只能通過(guò)判斷文件的的大小來(lái)確認(rèn)文件是否已經(jīng)傳輸完成。
解決代碼代碼
//dis就是DataInputStream String fileName = dis.readUTF();//文件名字 long fileLength = dis.readLong();//文件長(zhǎng)度 File directory = new File(savepath); if(!directory.exists()) { directory.mkdir(); } File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName); fos = new FileOutputStream(file); // 開(kāi)始接收文件 byte[] bytes = new byte[1024]; //byte[] bytes = new byte[dis.available()]; int length = 0; while((length = dis.read(bytes, 0, bytes.length)) != -1) { System.out.println(bytes.length); //fos就是FileOutputStream fos.write(bytes, 0, length); fos.flush(); //*************關(guān)鍵的一步**************// if(fileLength == file.length()) break; //***************************// } System.out.println("======== 文件接收成功 [File Name:" + fileName + "] [Size:" + getFormatFileSize(fileLength) + "] ========");
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis查詢語(yǔ)句返回對(duì)象和泛型集合的操作
這篇文章主要介紹了Mybatis查詢語(yǔ)句返回對(duì)象和泛型集合的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07java實(shí)現(xiàn)MapReduce對(duì)文件進(jìn)行切分的示例代碼
本文主要介紹了java實(shí)現(xiàn)MapReduce對(duì)文件進(jìn)行切分的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01SpringBoot配置MySQL5.7與MySQL8.0的異同點(diǎn)詳解
MySQL 是 Java 開(kāi)發(fā)中最常用的數(shù)據(jù)庫(kù)之一,而 Spring Boot 提供了便捷的配置方式,隨著 MySQL 8.0 的普及,許多開(kāi)發(fā)者需要從 MySQL 5.7 升級(jí)到 8.0,在實(shí)際開(kāi)發(fā)中,二者的配置方式既有相似之處,也有一些需要特別注意的不同點(diǎn),所以本文給大家詳細(xì)介紹了它們的異同點(diǎn)2024-12-12Spring Boot 自動(dòng)裝配原理及 Starter 實(shí)現(xiàn)原理解析
SpringBoot通過(guò)@SpringBootApplication注解簡(jiǎn)化了依賴引入和配置,該注解包括@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三部分,感興趣的朋友跟隨小編一起看看吧2024-09-09使用SSM+Layui+Bootstrap實(shí)現(xiàn)汽車(chē)維保系統(tǒng)的示例代碼
本文主要實(shí)現(xiàn)對(duì)汽車(chē)維修廠的信息化管理功能,。實(shí)現(xiàn)的主要功能包含用戶管理、配置管理、汽車(chē)管理、故障管理、供應(yīng)商管理、配件管理、維修訂單管理、統(tǒng)計(jì)信息、公告管理、個(gè)人信息管理,感興趣的可以了解一下2021-12-12