@mrRobot1983

В чем ошибка(java/socket/file transfer)?

Всем добрый день!Пишу приложение которое пересылает файлы с клиента на сервер.С одним файлом все работает отлично,но когда отправляются несколько файлов,генерируется exception
Exception in thread "main" java.lang.NegativeArraySizeException
at double2.code.code1.Receiver.receiveFile(Receiver.java:45)
at double2.code.code1.Receiver.main(Receiver.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Код сервера:
public class Sender {

static ServerSocket server;
static final int PORT = 6666;
static ArrayList<Socket> sockets;
static String basePath = "C:\\as\\server";
public static void main(String[] args) throws IOException {
    server =new ServerSocket(PORT);
    sockets = new ArrayList<Socket>();

    String fileName ="111.jpg";

    ArrayList<String>locations = new ArrayList<String>();
    locations.add(fileName);
    locations.add("1.jpg");


    Socket socket = server.accept();

    Sender.send(socket,locations);

    socket.close();

}
static void sendFileNames(Socket socket,ArrayList<String>fileNames) throws IOException {
    DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
    dataOutputStream.writeInt(fileNames.size());//отправляем размер
    for (String name:fileNames){
        dataOutputStream.writeUTF(name);
    }
}
public static  void send(Socket socket,ArrayList<String> fileNames) throws IOException {
    FileInputStream fileInputStream = null;
    BufferedInputStream bufferedInputStream = null;

    DataOutputStream outputStream = null;
    try {
        System.out.println("Waiting for receiver...");
            try {
                    System.out.println("Accepted connection : " + socket);
                sendFileNames(socket,fileNames);
                for(String fileName:fileNames) {
                    File file = new File(basePath + "\\"+fileName);
                    byte[] byteArray = new byte[(int) file.length()];
                    System.out.println("lol");
                    outputStream = new DataOutputStream(socket.getOutputStream());
                    outputStream.writeLong(file.length());//TODO
                    System.out.println("lol");
                    fileInputStream = new FileInputStream(file);
                    bufferedInputStream = new BufferedInputStream(fileInputStream);
                    bufferedInputStream.read(byteArray, 0, byteArray.length); // copied file into byteArray

                    System.out.println("Sending " + fileName + "( size: " + byteArray.length + " bytes)");
                    outputStream.write(byteArray, 0, byteArray.length);
                    outputStream.flush();                                        //flushing socket
                    System.out.println("Done.");
                }
                }
                finally {
                    if (bufferedInputStream != null) bufferedInputStream.close();
                    if (outputStream != null) bufferedInputStream.close();
                    if (socket!=null) socket.close();
                }       
        } catch (IOException e) {

            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally {
            if (server != null) server.close();
        }
}
}

код клиента:
public class Receiver {

static Socket socket;
static final int PORT = 6666;
static final String IP = "127.0.0.1";
static DataInputStream dim;
static String basePath = "C:\\as\\client";
public static void main (String [] args ) throws IOException {

    socket = new Socket(IP,PORT);

    receiveFile();

    System.out.println("yeeee");

}
static ArrayList<String>readFileNames() throws IOException {
    ArrayList<String>res = new ArrayList<String>();
    DataInputStream din = new DataInputStream(socket.getInputStream());
    int lenght = din.readInt();
    for(int i = 0;i<lenght;i++){
        String name = din.readUTF();
        res.add(name);
    }
    return res;
}
public static void receiveFile() throws IOException {
    int bytesRead = 0;
    int current = 0;
    FileOutputStream fileOutputStream = null;
    BufferedOutputStream bufferedOutputStream = null;
    try {
        ArrayList<String> locations = readFileNames();

        for (String location:locations) {
            dim = new DataInputStream(socket.getInputStream());
            long res = dim.readLong();
            System.out.println("res "+res);
            byte[] byteArray = new byte[(int) res + 1];
            System.out.println("sizze" + res);

            System.out.println("Please wait downloading file");

            DataInputStream inputStream = new DataInputStream(socket.getInputStream());
            File f = new File(basePath + "\\" + location);
            fileOutputStream = new FileOutputStream(f);

            System.out.println(f.createNewFile());

            //TODO !!!!!!!!!!!
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            bytesRead = inputStream.read(byteArray, 0, byteArray.length);                    //copying file from socket to byteArray

            current = bytesRead;
            System.out.println("hah");
            do {
                bytesRead = inputStream.read(byteArray, current, (byteArray.length - current));
                System.out.println(current);
                if (current == res)
                    break;
                if (bytesRead >= 0) current += bytesRead;
            } while (bytesRead > -1);
            bufferedOutputStream.flush();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {
        if (fileOutputStream != null) fileOutputStream.close();
        if (bufferedOutputStream != null) bufferedOutputStream.close();
    }
}
}

Логированием увидел что во 2 раз передается какое-то левое значение размера файла,и скорее всего из-за этого формируется ошибка.Подскажите пожалуйста,как мне решить эту проблему.
  • Вопрос задан
  • 377 просмотров
Решения вопроса 1
@zelan
Кратко обо мне не получится.
long res = dim.readLong();
            System.out.println("res "+res);

            //здесь ты приводишь long к int, и может произойти переполнение,
            // и размерность массива будет отрицательной. Из-за этого вылетает эксепшн
            byte[] byteArray = new byte[(int) res + 1];


во второй раз ты передаешь длину массива которую прочитал сервер
и опять ты урезал длину ограничив интом
File file = new File(basePath + "\\"+fileName);
//вот здесь ты обрезал получаемою длину файла, и от потока требуешь в будущем прочитать данные в этот массив
//но читаешь ты только кусок
//опять же здесь ты можешь снова получить отрицательное значение размерности массива
byte[] byteArray = new byte[(int) file.length()];

//и во второй раз ты передаешь длину ОБРЕЗАННОГО МАССИВА который в реальности смог прочитать здесь
bufferedInputStream.read(byteArray, 0, byteArray.length); // copied


не складируй данные в массив, передавай длину лонгом (или вообще не передавай , незачем она), а потом в цикле читай побайтово через read() (метод возвращает int - и как только он вернет -1 значит данные кончились) и сразу пиши в файл.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
18 сент. 2019, в 09:40
1000 руб./за проект
18 сент. 2019, в 09:35
20000 руб./за проект
18 сент. 2019, в 08:49
10000 руб./за проект