Java 在块中读取字节时套接字InputStream出现故障
我正在通过套接字连接编写简单的文件传输,我遇到了一个问题 以字节块形式下载文件时。当我一次读取一个字节时,一切正常,但当我尝试读取512字节的块时,在下载文件的所有字节后(我知道长度,这要归功于我的头),套接字开始接收一些随机字节,最终出现崩溃,因为2x“%”已找到,并且服务器尝试计算传入消息的长度,但没有可开始的长度Java 在块中读取字节时套接字InputStream出现故障,java,file,sockets,byte,inputstream,Java,File,Sockets,Byte,Inputstream,我正在通过套接字连接编写简单的文件传输,我遇到了一个问题 以字节块形式下载文件时。当我一次读取一个字节时,一切正常,但当我尝试读取512字节的块时,在下载文件的所有字节后(我知道长度,这要归功于我的头),套接字开始接收一些随机字节,最终出现崩溃,因为2x“%”已找到,并且服务器尝试计算传入消息的长度,但没有可开始的长度 @Override public void run() { while (client.isConnected() && !client.is
@Override
public void run() {
while (client.isConnected() && !client.isClosed() && !client.isInputShutdown()){
try {
readResponse();
clientWriter.write("0%"); /// IF IT CATCHES EXCEPTION SOCKET CLOSED ON THE OTHER SIDE(DON'T KNOW HOW TO CHECK IT IN ANOTHER WAY)
}
catch (IOException e) {
System.out.println(e.toString());
return;
}
catch (InterruptedException e) {
System.out.println(e.toString());
return;
}
}
}
private void readResponse() throws IOException, InterruptedException {
int length = 0;
int ch;
FileOutputStream file = new FileOutputStream("holder");
boolean bWrite = false;
StringBuilder name = new StringBuilder();
int percentageCount = 0;
String filename="";
length = 0;
int l = 0;
int old = 0;
while ((ch=client.getInputStream().read())!=-1){
if (!bWrite) {
name.append(Character.toChars(ch));
}
if (ch==37 && !bWrite){
if (percentageCount<1){
percentageCount++;
} else {
filename = name.toString();
length = Integer.parseInt(filename.substring(0,filename.indexOf("%")));
l = length;
filename = filename.substring(filename.indexOf("%")+1);
filename = filename.substring(0,filename.indexOf("%"));
file = new FileOutputStream(filename);
bWrite = true;
break;
}
}
}
byte[] bytes = new byte[512];
while (length>=512){
client.getInputStream().read(bytes, 0, 512);
file.write(bytes, 0, 512);
length-=512;
}
if (length>0){
bytes = new byte[length];
client.getInputStream().read(bytes,0,length);
file.write(bytes,0,length);
length = 0;
}
file.flush();
file.close();
}
@覆盖
公开募捐{
while(client.isConnected()&&&!client.isClosed()&&!client.isInputShutdown()){
试一试{
readResponse();
clientWriter.write(“0%”;///如果它捕获到另一侧关闭的异常套接字(不知道如何用另一种方式检查它)
}
捕获(IOE异常){
System.out.println(例如toString());
返回;
}
捕捉(中断异常e){
System.out.println(例如toString());
返回;
}
}
}
private void readResponse()引发IOException、InterruptedException{
整数长度=0;
int-ch;
FileOutputStream文件=新的FileOutputStream(“持有者”);
布尔bWrite=false;
StringBuilder名称=新的StringBuilder();
int percentageCount=0;
字符串filename=“”;
长度=0;
int l=0;
int old=0;
而((ch=client.getInputStream().read())!=-1){
如果(!bWrite){
name.append(Character.toChars(ch));
}
if(ch==37&&!bWrite){
如果(百分比计数=512){
client.getInputStream().read(字节,0,512);
写入(字节,0,512);
长度-=512;
}
如果(长度>0){
字节=新字节[长度];
client.getInputStream().read(字节,0,长度);
file.write(字节,0,长度);
长度=0;
}
flush()文件;
file.close();
}
代码的最后一部分可以更改为(未测试):
byte[]bytes=新字节[512];
InputStream=client.getInputStream();
而(长度>0){
int read=is.read(bytes,0,Math.min(bytes.length,length));
如果(读取>0){
文件写入(字节,0,读取);
长度-=读取;
}
如果(读取<0)
抛出新的IOException(“在读取所有数据之前达到结束”;
}
这将正确地检查返回的大小,避免两个循环并检查流的结尾
BTW2:
getInputStream()
相当重,只能执行一次(我示例中的是
应该在方法开始时检索,尤其是在读取循环之前)。btw我的头格式是:%%您需要先清理循环。不要执行client.getInputStream().read()之类的操作
并尝试删除与您的问题无关的所有代码。很难找到想要读取所有代码的人。一个明显的问题是,您读取了512字节的缓冲区,但没有实际检查返回了多少字节。您必须使用read(仅写入readLen字节)的返回值。这种情况在您的代码中发生了2次。尤其是长度较大的第二次将失败。是否删除任何其他内容?我知道这有点混乱,但应该都能正常工作如果一切正常,那么您为什么要问?:)还有一个问题,如何最好地检测另一方面是否关闭了套接字?除非您发送/接收某种形式的心跳消息,否则无法在所有情况下检测到它。您可以为套接字打开,但这将仅在数小时后检测(典型的操作系统设置)。但是,如果操作系统检测到它,您将在读取时获得-1,或在写入时获得异常。您应该在协议中包含一条“我完成了”消息,以便可以完全关闭。@Peter Lawrey有一个-1的示例:
byte[] bytes = new byte[512];
InputStream is = client.getInputStream();
while (length>0) {
int read = is.read(bytes, 0, Math.min(bytes.length, length));
if (read > 0) {
file.write(bytes, 0, read);
length-=read;
}
if (read < 0)
throw new IOException("end reached before all data read";
}