Reputation: 1971
I'm writing simple file transfer through socket connection and I have a problem while downloading a file in chunks of bytes. When I read one byte at a time everything works but when I try to read for example in chunks of 512 bytes, after downloading all the bytes of the file(I know the length thanks to my header), the socket starts receiving some random bytes and eventually there is a crash because 2x "%" were found and the server tries to count the length of incoming message, when there is none to begin with.
@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();
}
Upvotes: 1
Views: 1600
Reputation: 10423
The last part of the code can be changed to (untested):
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";
}
This correctly checks the returned size, it avoids two loops and checks for end of stream.
BTW2: getInputStream()
is pretty heavy weight, it should only be done once (the is
from my example should be retrieved at the beginning of the method, especially before the read loop).
Upvotes: 2