2012-04-19 5 views
0

Хорошо ... Попытка самостоятельно изучить Java, возникла проблема с этим на некоторое время. Я пытаюсь передать большой файл по сети с помощью сокетов и буферизованных потоков ввода и вывода. Неважно, какой размер файла я пытаюсь передать. Надеюсь, я правильно разместил свой код, я знаю, что, вероятно, многие проблемы с этим кодом, хотя он компилируется и работает нормально, я получаю IndexOutOfBoundsException, второй клиент и сервер идут в циклы while, сервер получает его во время первого бис.read (ЬиЕ, 0, длина), и клиент получает его во время (от = fis.read (ЬиЕ, 0, длина) ..... Любая помощь будет принята с благодарностьюПередача сокета Java, буферизованный ввод и вывод

//Server Receive code receive method and main for testing 
    public File receive(Socket socket) throws IOException{ 

     //temporarily hard coded filename 
     File file = new File("C:\\users\\tom5\\desktop\\sales\\input.dat"); 
     DataInputStream dis = new DataInputStream(socket.getInputStream()); 
     FileOutputStream fos = new FileOutputStream(file); 
     BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); 
     //reads file length from datainputstream 
     int len = dis.readInt(); 
     dis.close(); 
     int bytesRead=0; 
     //create buffer 
     byte[]buf = new byte[4092]; 
     int off = 0; 

     //read from BufferedInputStream and write to FileOutputStream? 
     while(bytesRead < len) { 
      bis.read(buf,0,len); 
      fos.write(buf,0,len); 
      bytesRead++; 
     } 
     fos.close(); 
     bis.close(); 
     return file; 
    } 
    public static void main(String[]args) throws IOException{ 
     Server server = new Server(); 
     Socket socket =server.accept(); 
     File file = server.receive(socket); 
    } 
} 

//Client sending code 

    public void send(Socket socket,File file) throws IOException{ 
     FileInputStream fis = new FileInputStream(file); 
     DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); 
     BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); 
     int len = (int)file.length(); 
     dos.writeInt(len); 
     dos.flush(); 
     dos.close(); 
     System.out.println(file.length()); 

     byte[]buf = new byte[4092]; 
     int off= 0; 
     while((off = fis.read(buf,0,len)) != -1 ){ 
      bos.write(buf,0,len);  
     } 
    } 

    public static void main(String[]args) throws UnknownHostException, IOException{ 
     Client client = new Client(); 
     Socket socket =client.connect("localhost",1055); 
     File file = new File("C:\\users\\tom5\\desktop\\movie.avi"); 
    } 
} 
+0

Oen вещь, которую я заметил сразу с места в карьер, состоит в том, что у вас есть * два метода '' main'. – fireshadow52

+1

Я считаю, что это код для сервера и для клиента, не работающий одновременно. –

+0

@NickMartin А я вижу. Сожалею! – fireshadow52

ответ

3
while(bytesRead < len) { 
    bis.read(buf,0,len); 
    fos.write(buf,0,len); 
    bytesRead++; 
} 

You попробуйте прочитать len байт в buf, который больше его длины, и каждый раз увеличивайте байты на 1, хотя read может читать несколько байтов. Это должно быть больше похоже:

while(bytesRead < len) { 
    int n = bis.read(buf); 
    fos.write(buf, 0, n); 
    bytesRead += n; 
} 

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

while(bytesRead < len) { 
    int n = bis.read(buf, 0, Math.min(buf.length, len - bytesRead)); 
    fos.write(buf, 0, n); 
    bytesRead += n; 
} 

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

0

Вы обертываете поток дважды, один раз как dis и один раз как bis. Это означает, что это не буферизировано, но когда вы закрываете его, вы закрываете базовый поток.

Я предлагаю вам завернуть ТОЛЬКО ДЛЯ ИСПОЛЬЗОВАНИЯ

DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream())); 

Если вы хотите эффективный размер буфера, то я предлагаю вам силу 2, то есть 4096, а не 4092.

A @fgb примечания: Вы исправить используйте длину read() для размера отправки, но игнорируйте ее на размер получателя (ирония заключается в том, что вы обычно получаете размер, который вы запрашиваете при чтении файла, но не так много при чтении сокета)

Рассмотрите возможность использования один общий метод ввода-вывода InputStream для OutputStream, который wo в обеих ситуациях, например. как IOUtils.copy().

+0

имеет смысл, не понимал, что могу обернуть DataInputStream в BufferedInputStream, прежде чем я использовал только поток DIS для чтения Ints и UTF. –

0

Вы используете фиксированный размер буфера. Попробуйте следующее:

byte[] mybytearray = new byte[(int) myFile.length()]; 
Смежные вопросы