Как правильно записать данные файла? - PullRequest
2 голосов
/ 06 июля 2011

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

Мне удалось успешно отправить небольшие файлы .doc и .txt, но .mp3 .wmv .m4a .aviи ни о чем другом не работает.Ни один не делает больших документов.

Я искал во всем Интернете для решения этой проблемы.Я неоднократно подправлял код ввода / вывода, чтобы исправить проблему, но он все еще не работает!Вот код ввода / вывода в суперклассе, который обрабатывает отправку и получение файлов.Если вам нужна дополнительная информация / другие части кода, дайте мне знать.

protected void sendFile() throws IOException {
    byte[] bytes = new byte[(int) file.length()];
    buffin = new BufferedInputStream(new FileInputStream(file));
    int bytesRead = buffin.read(bytes,0,bytes.length);
    System.out.println(bytesRead);
    out = sock.getOutputStream();
    out.write(bytes,0,fileBytes);
    out.flush();
    out.close();
}

protected void receiveFile() throws IOException {
    byte[] bytes = new byte[fileBytes];
    in = sock.getInputStream();
    for(int i=0;i<fileBytes;i++) {
        in.read(bytes);
    }
    fos = new FileOutputStream("/Datawire/"+fileName);
    buffout = new BufferedOutputStream(fos);
    buffout.write(bytes,0,fileBytes);
    buffout.flush();
    buffout.close();
}

ОБНОВЛЕННЫЙ КОД (работает):

    protected void sendFile() throws IOException {
    if((file.length())<63000) {
        byte[] bytes = new byte[(int)file.length()];
        buffin = new BufferedInputStream(new FileInputStream(file));
        buffin.read(bytes,0,bytes.length);
        out = sock.getOutputStream();
        out.write(bytes,0,bytes.length);
        out.close();
    } else {
        byte[] bytes = new byte[32000];
        buffin = new BufferedInputStream(new FileInputStream(file));
        out = sock.getOutputStream();
        int bytesRead;
        while((bytesRead = buffin.read(bytes))>0) {
            out.write(bytes,0,bytesRead);
        }
        out.close();
    }
}

protected void receiveFile() throws IOException {
    if(fileBytes<63000) {
        byte[] bytes = new byte[32000];
        in = sock.getInputStream();
        System.out.println(in.available());
        in.read(bytes,0,fileBytes);
        fos = new FileOutputStream("/Datawire/"+fileName);
        buffout = new BufferedOutputStream(fos);
        buffout.write(bytes,0,bytes.length);
        buffout.close();
    } else {
        byte[] bytes = new byte[16000];
        in = sock.getInputStream();
        fos = new FileOutputStream("/Datawire/"+fileName);
        buffout = new BufferedOutputStream(fos);
        int bytesRead;
        while((bytesRead = in.read(bytes))>0) {
            buffout.write(bytes,0,bytesRead);
        }
        buffout.close();
    }
}

Ответы [ 5 ]

2 голосов
/ 06 июля 2011

Проблема в том, что вы отправляете только куски этого.То есть вы отправляете только 64 КБ файла.Если размер файла больше 64 КБ, другой конец его никогда не увидит.

Вы хотите непрерывно читать из BufferedInputStream до тех пор, пока read () не вернёт либо меньше длины, либо -1.

1 голос
/ 07 июля 2011

Ваш код полностью неверен.Вот как скопировать поток в Java:

int count;
byte[] buffer = new byte[8192]; // more if you like but no need for it to be the entire file size
while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}

Вы должны использовать это как при отправке файла, так и при получении файла.В настоящее время ваш метод отправки надеется, что весь файл помещается в память;вписывается в байты INTEGER_MAX;и читается в одном блоке методом чтения, даже не проверяя результат.Вы не можете предполагать что-либо из этого.Ваш метод приема - полный мусор: он просто продолжает перезаписывать тот же массив, опять же без проверки каких-либо результатов read ().

РЕДАКТИРОВАТЬ: Ваш исправленный код такой же плохой или хуже.Вы вызываете read () для проверки EOS, затем отбрасываете этот байт, затем снова вызываете read () и отбрасываете счетчик чтения, который он возвращает.У вас бессмысленно есть другой путь для файлов <64000, или 63000, или что бы то ни было, который имеет нулевое преимущество, за исключением предоставления вам двух путей кода для тестирования, или, возможно, четырех, вместо одного.В любом случае, сеть дает в лучшем случае только 1460 байт, так какой смысл?У вас уже есть (a) BufferedInputStream с размером буфера по умолчанию 8192 и (b) мой код, который использует буфер byte [] любого размера, который вам нравится.Мой код выше работает для любого объема данных в две строки исполняемого кода.У тебя 20. КЭД. </p>

1 голос
/ 06 июля 2011

Я предлагаю вам использовать хорошую библиотеку для чтения и записи содержимого файла, а также для чтения / записи через сокет. Например, Apache Commons IO. Если вы настаиваете на написании кода самостоятельно, делайте его небольшими порциями, а не целым файлом сразу.

0 голосов
/ 07 июля 2011

Необходимо выполнить цикл до bytesRead <0. Необходимо убедиться, что <em>fileBytes = => чем переданный файл.

protected void receiveFile() throws IOException {
    byte [] bytes  = new byte [fileBytes];
    InputStream is = sock.getInputStream();
    FileOutputStream fos = new FileOutputStream("/Datawire/"+fileName);
    BufferedOutputStream bos = new BufferedOutputStream(fos);

    int bytesRead = is.read(bytes,0,bytes.length);
    int current = bytesRead;

    do {
       bytesRead =
          is.read(bytes, current, (bytes.length-current));
       if(bytesRead >= 0) current += bytesRead;
    } while(bytesRead > -1);

    bos.write(bytes, 0 , current);
    bos.flush();
    bos.close();

}
0 голосов
/ 06 июля 2011

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

Возможно, вам было бы лучше, если бы что-то вроде CopyUtils.copy позаботилось об этом за вас.

...