Java 数据输入流长度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5947365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:36:21  来源:igfitidea点击:

Java DataInputStream length

javasockets

提问by David Weng

I am creating a file server application for school assignment. What I currently have is a simple Clientclass that sends an image through TCP and a Serverclass that receives it and writes it to the file.

我正在为学校作业创建一个文件服务器应用程序。我目前拥有的是一个Client通过 TCP 发送图像的简单类和一个Server接收图像并将其写入文件的类。

this is my client code

这是我的客户端代码

import java.io.*;
import java.net.*;

class Client {
    public static void main(String args[]) throws Exception {
        long start = System.currentTimeMillis();
        Socket clientSocket = new Socket("127.0.0.1", 6789);
        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());

        File file = new File("hot.jpg");
        FileInputStream fin = new FileInputStream(file);
        byte sendData[] = new byte[(int)file.length()];
        fin.read(sendData);

        outToServer.write(sendData, 0, sendData.length);
        clientSocket.close();

        long end = System.currentTimeMillis();
        System.out.println("Took " + (end - start) + "ms");
    }
}

and this is my server code.

这是我的服务器代码。

import java.io.*;
import java.net.*;

class Server {
    public static void main(String args[]) throws Exception {
        ServerSocket serverSocket = new ServerSocket(6789);
        Socket connectionSocket = serverSocket.accept();
        DataInputStream dis = new DataInputStream(connectionSocket.getInputStream());

        byte[] receivedData = new byte[61500]; // <- THIS NUMBER

        for(int i = 0; i < receivedData.length; i++)
            receivedData[i] = dis.readByte();

        connectionSocket.close();
        serverSocket.close();

        FileOutputStream fos = new FileOutputStream("received.jpg");
        fos.write(receivedData);
        fos.close();
    }
}

My question is how to get the size of the file that is being sent. If you check the Servercode you'll see that I've hardcoded the number i.e. 61500 at the moment. How can I retrieve this number dynamically?

我的问题是如何获取正在发送的文件的大小。如果您检查Server代码,您会发现我现在已经对数字进行了硬编码,即 61500。如何动态检索此号码?

Or, am I doing this the wrong way? What an alternative solution would be?

或者,我这样做是错误的吗?什么替代解决方案是?

回答by dacwe

Add one "length field" before sending the file. (Note that since you read the file to memory the maximum size of the file can be ~2GB.)

在发送文件之前添加一个“长度字段”。(请注意,由于您将文件读取到内存中,文件的最大大小可以为 ~2GB。)



Before sending the file write the length of the file:

在发送文件之前写入文件的长度:

  outToServer.writeInt(sendData.length);

And when receiving read the length first and use it as a length:

接收时首先读取长度并将其用作长度:

  int dataLength = dis.readInt()
  byte[] receivedData = new byte[dataLength];


A better way would be notto read the file into memory first but to transfer it directly from the FileInputStream- then you could transfer bigger files!

更好的方法不是先将文件读入内存,而是直接从内存中传输它FileInputStream——然后你就可以传输更大的文件!

回答by Peter Lawrey

If you know the length, using readFully() is much more efficient than reading a byte at a time.

如果您知道长度,使用 readFully() 比一次读取一个字节更有效。

In this case, you don't need to know the length, you can write the loop to read/write as much data as you get.

在这种情况下,您不需要知道长度,您可以编写循环来读取/写入尽可能多的数据。

InputStream is = connectionSocket.getInputStream();

byte[] bytes = new byte[8192];
int len;
while((len = is.read(bytes)) > 0)
    fos.write(bytes, 0, len);

You can avoid reading the whole file into memory by copying the data as you read it.

您可以通过在读取数据时复制数据来避免将整个文件读入内存。

FileInputStream fis = new FileInputStream(filename);
OutputStream os = socket.getOutputStream();

byte[] bytes = new byte[8192];
int len;
while((len = fis.read(bytes)) > 0)
    os.write(bytes, 0, len);

You can use Apache IOUtils.copy() to perform the copy from one stream to another if you wish.

如果您愿意,您可以使用 Apache IOUtils.copy() 执行从一个流到另一个流的复制。

This approach has the advantage that the file can be any size (greater than 2 GB). Using an array is limited to 2 GB (and uses more memory)

这种方法的优点是文件可以是任意大小(大于 2 GB)。使用数组限制为 2 GB(并使用更多内存)