【问题标题】:How to detect end of a file while receiving it through InputStream如何在通过 InputStream 接收文件时检测文件的结尾
【发布时间】:2014-08-06 10:16:49
【问题描述】:

我正在尝试通过套接字发送多个文件。我写的发送者和接收者函数如下所示。 发件人

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() 可能无法读取完整数据。 但是如果我使用这个接收器,我应该得到整个文件。 接收器2

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

感谢大家帮助我。

【问题讨论】:

  • 在写入文件之前将整个文件读入内存并不是一个好主意。您需要为 Receiver1 设置一个额外的循环,以确保读取所有字节。
  • 发送文件前,发送文件大小
  • 这就是我在receiver2中尝试做的事情。 @Kayaman
  • 我已经完成了。 @SpaceTrucker

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


【解决方案1】:

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

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

电子与工程

【讨论】:

  • 此代码的工作方式与我的接收器 1 相同。它没有获取整个文件。谢谢@EJP
  • @Ifta 如果此代码没有获取整个文件,则说明您没有发送整个文件,或者您发送的字长不正确。
  • 嗨,我问这个问题已经 6 年了,你已经回答了。我当时把那个代码弄到了工作状态。也许你的回答有帮助。其实我不记得了。但是现在再次阅读问题和答案,我意识到您的答案是正确的并标记为已接受。非常感谢您的帮助。
猜你喜欢
  • 2020-02-22
  • 2013-07-12
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
相关资源
最近更新 更多