简体   繁体   English

Java DataInputStream长度

[英]Java DataInputStream length

I am creating a file server application for school assignment. 我正在为学校作业创建一个文件服务器应用程序。 What I currently have is a simple Client class that sends an image through TCP and a Server class 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 Server code you'll see that I've hardcoded the number ie 61500 at the moment. 如果你检查Server代码,你会看到我已经硬编码了这个数字,即61500。 How can I retrieve this number dynamically? 如何动态检索此数字?

Or, am I doing this the wrong way? 或者,我这样做是错误的吗? What an alternative solution would be? 什么是替代解决方案?

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 not to read the file into memory first but to transfer it directly from the FileInputStream - then you could transfer bigger files! 更好的方法是先将文件读入内存,而是直接从FileInputStream传输 - 然后你可以传输更大的文件!

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). 此方法的优点是文件可以是任何大小(大于2 GB)。 Using an array is limited to 2 GB (and uses more memory) 使用数组限制为2 GB(并使用更多内存)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM