Длина Java DataInputStream - PullRequest
5 голосов
/ 10 мая 2011

Я создаю приложение файлового сервера для школьного задания.В настоящее время у меня есть простой Client класс, который отправляет изображение через TCP и Server класс, который получает его и записывает в файл.

это мой код клиента

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

и это мой код сервера.

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

Мой вопрос: как определить размер отправляемого файла?Если вы проверите код Server, вы увидите, что я жестко закодировал номер, то есть 61500 на данный момент.Как я могу получить этот номер динамически?

Или я делаю это неправильно?Каким было бы альтернативное решение?

Ответы [ 2 ]

7 голосов
/ 10 мая 2011

Добавьте одно «поле длины» перед отправкой файла. (Обратите внимание, что поскольку вы считываете файл в память, максимальный размер файла может составлять ~ 2 ГБ.)


Перед отправкой файла запишите длину файла:

  outToServer.writeInt(sendData.length);

И при получении сначала прочитайте длину и используйте ее как длину:

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

Лучшим способом было бы , а не для чтения файла всначала память, но перенести ее прямо из FileInputStream - тогда вы можете передавать большие файлы!

2 голосов
/ 10 мая 2011

Если вы знаете длину, использование readFully () намного эффективнее, чем чтение байта за раз.

В этом случае вам не нужно знать длину, вы можете написать цикл для чтения / записи как можно большего количества данных.

InputStream is = connectionSocket.getInputStream();

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

Вы можете избежать чтения всего файла в память, копируя данные по мере их чтения.

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

Вы можете использовать Apache IOUtils .copy () для выполнения копирования из одного потока в другой, если хотите.

Преимущество этого подхода заключается в том, что файл может иметь любой размер (более 2 ГБ). Использование массива ограничено 2 ГБ (и использует больше памяти)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...