Reputation: 1595
I am trying to send multiple files through socket. The sender and receiver function i wrote is given below. Sender
public void sendFileX() throws IOException {
DataOutputStream dos = new DataOutputStream(
connection.getOutputStream());
//send file number
dos.writeInt(filesToSend.length);
dos.flush();
//send file names
for (int i = 0; i < filesToSend.length; i++) {
dos.writeUTF(filesToSend[i].getName());
}
dos.flush();
//send file sizes
for (int i = 0; i < filesToSend.length; i++) {
File myFile = new File("" + filesToSend[i] + "");
dos.writeLong(myFile.length());
}
dos.flush();
// send the file
os = connection.getOutputStream();
for (int i = 0; i < filesToSend.length; i++) {
File myFile = new File("" + filesToSend[i] + "");
byte[] mybytearray = new byte[(int) myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray, 0, mybytearray.length);
os.write(mybytearray, 0, mybytearray.length);
}
os.flush();
os.close();
bis.close();
}
And the receiver is: Receiver
private void recieveFileY() throws IOException
{
DataInputStream dis = new DataInputStream(connection.getInputStream());
//receive file number
int len = dis.readInt();
//receive file names
fileNames = new String[len];
for(int i = 0; i < len; i++)
{
fileNames[i] = dis.readUTF();
}
//receive file sizes
fileSizes = new long[len];
for(int i = 0; i < len; i++)
{
fileSizes[i] = dis.readLong();
}
for(int i = 0; i <len; i++)
{
System.out.println(fileNames[i]+", size: "+fileSizes[i]);
}
//receive files
is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for(int i = 0; i < len; i++)
{
String fileSaveLocation = "c:/"+fileNames[i];
fos = new FileOutputStream(fileSaveLocation);
bos = new BufferedOutputStream(fos);
byte[] bytesToRead = new byte[(int) fileSizes[i]];
is.read(bytesToRead, 0, bytesToRead.length);
bos.write(bytesToRead);
}
For this receiver I am getting all files but some file have data missing as is.read() may not read full data. But if I use this receiver , I supposed to get the whole file. Receiver2
private void recieveFileX() throws IOException
{
DataInputStream dis = new DataInputStream(connection.getInputStream());
//receive file number
int len = dis.readInt();
//receive file names
fileNames = new String[len];
for(int i = 0; i < len; i++)
{
fileNames[i] = dis.readUTF();
}
//receive file sizes
fileSizes = new long[len];
for(int i = 0; i < len; i++)
{
fileSizes[i] = dis.readLong();
}
for(int i = 0; i <len; i++)
{
System.out.println(fileNames[i]+", size: "+fileSizes[i]);
}
//receive files
is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for(int i = 0; i < len; i++)
{
String fileSaveLocation = "c:/"+fileNames[i];
fos = new FileOutputStream(fileSaveLocation);
bos = new BufferedOutputStream(fos);
byte[] bytesToRead = new byte[(int) fileSizes[i]];
bytesRead = is.read(bytesToRead, 0, bytesToRead.length);
current = bytesRead;
do {
bytesRead = is.read(bytesToRead, current,
(bytesToRead.length - current));
if (bytesRead >= 0)
current += bytesRead;
System.out.println("I am in do while loop");
} while (bytesRead > -1);
bos.write(bytesToRead);
System.out.println("Saved " + fileNames[i]);
}
bos.flush();
bos.close();
is.close();
}
But the problem here is after finishing reading one file more data is available in inputStream so is.read() does not return -1 to bytesRead and I got stuck in infinity loop. Please anyone help me. Thanks in advance.
FINALLY MY CODE WORKED
private void recieveFileX() throws IOException
{
DataInputStream dis = new DataInputStream(connection.getInputStream());
//receive file number
int len = dis.readInt();
//receive file names
fileNames = new String[len];
for(int i = 0; i < len; i++)
{
fileNames[i] = dis.readUTF();
}
//receive file sizes
fileSizes = new long[len];
for(int i = 0; i < len; i++)
{
fileSizes[i] = dis.readLong();
}
for(int i = 0; i <len; i++)
{
System.out.println(fileNames[i]+", size: "+fileSizes[i]);
}
//receive files
is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
for(int i = 0; i < len; i++)
{
String fileSaveLocation = "c:/"+fileNames[i];
fos = new FileOutputStream(fileSaveLocation);
bos = new BufferedOutputStream(fos);
byte[] bytesToRead = new byte[(int) fileSizes[i]];
/*is.read(bytesToRead, 0, bytesToRead.length);
bos.write(bytesToRead);
bos.flush();
int count;
while ((count = is.read(bytesToRead)) > 0)
{
bos.write(bytesToRead, 0, count);
}
bytesRead = is.read(bytesToRead, 0, bytesToRead.length);
current = bytesRead;
do {
bytesRead = is.read(bytesToRead, current,
(bytesToRead.length - current));
if (bytesRead >= 0)
current += bytesRead;
System.out.println("I am in do while loop");
} while (bytesRead > -1);*/
while(true)
{
bytesRead = is.read(bytesToRead,current,(bytesToRead.length - current));
System.out.println("BytesRead = " + bytesRead);
if(bytesRead <=0)
{
System.out.println("loop breker 1 worked");
break;
}
current += bytesRead;
if(current == fileSizes[i])
{
System.out.println("loop breker 2 worked");
break;
}
System.out.println("Current = " + current);
}
bos.write(bytesToRead);
System.out.println("Saved " + fileNames[i]);
current = 0;
}
bos.flush();
bos.close();
is.close();
}
Thanks Everybody for helping me.
Upvotes: 0
Views: 3176
Reputation: 310884
You're using two different kinds of copy loop. In this one:
is.read(bytesToRead, 0, bytesToRead.length);
you're completely ignoring the return value. It could be -1 indicating end of file, or it could be a read count. So you're also assuming that read()
fills the buffer. It isn't specified to do that. You don't need two different loops to do the same thing. Use the same code at both ends:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
This works with any buffer size greater than zero. I usually use 8192 but you can use more if you wish.
If you want to keep the socket open for more sends, you need to:
DataOutputStream.writeLong()
DataInputStream.readLong()
modify the copy loop to read exactly that many bytes:
long runningTotal = 0;
while (runningTotal < total && (count = in.read(buffer, 0, (int)Math.min(buffer.length, total-runningTotal)) > 0)
{
out.write(buffer, 0, count);
runningTotal += count;
}
E&OE
Upvotes: 1