如何通过InputStream接收文件时检测文件的结尾

时间:2014-08-06 10:16:49

标签: java sockets inputstream file-transfer multiple-file-upload

我正在尝试通过套接字发送多个文件。我写的发送器和接收器功能如下。 的发件人

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();
}

接收者是: 的接收器

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);

}

对于这个接收器,我得到所有文件但是有些文件缺少数据,因为is.read()可能无法读取完整数据。 但如果我使用这个接收器,我应该得到整个文件。 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();
}

但这里的问题是在完成读取一个文件之后,inputStream中有更多数据可用,因此is.read()不会返回-1到bytesRead并且我陷入了无限循环。 请有人帮助我。提前致谢。

最后我的代码工作

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();
}

谢谢大家帮助我。

1 个答案:

答案 0 :(得分:0)

您正在使用两种不同的复制循环。在这一个:

is.read(bytesToRead, 0, bytesToRead.length);

您完全忽略了返回值。它可以是-1表示文件结束,或者它可以是读取计数。所以你也假设read()填充了缓冲区。没有指定这样做。你不需要两个不同的循环来做同样的事情。在两端使用相同的代码:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

这适用于任何大于零的缓冲区大小。我通常使用8192,但如果你愿意,可以使用更多。

如果要保持套接字打开以进行更多发送,则需要:

  • 使用DataOutputStream.writeLong()
  • 发送文件前面的文件长度
  • 使用DataInputStream.readLong()
  • 在接收方阅读
  • 修改复制循环以准确读取多个字节:

    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