размер файла, отправленного сокетом, равен 0, и доступ заблокирован, если я не использую System.exit (0), как этого избежать?

У меня есть клиент для планшета Android, который отправляет и получает несколько файлов между ним и java-сервером, работающим на Windows 7. Все работает отлично, за исключением одной странной проблемы. один из файлов, в этом примере, transfer.pdf, который получен от клиентского планшета Android, не может быть открыт и показывает размер 0. когда я пытаюсь открыть этот файл, я получаю сообщение об ошибке от Adobe Reader «этот файл уже открыт или используется другим приложением».

единственный способ решить эту проблему - использовать System.exit(0) для закрытия всего приложения, если я сделаю это, файл покажет правильный размер и откроется без проблем. однако я бы предпочел не использовать System.exit(0). Я пробовал все, и ничего больше не работало.

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

у кого-нибудь еще была эта проблема и как я могу заставить ее работать без использования System.exit(0)?

код для сервера

public class MultiThreader implements Runnable {
Socket socket;
File fileDirectory;
File file;
public int fileSizeFromClient;
FileOutputStream fos = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
long length;

public MultiThreader(Socket socket){
    System.out.println("print out from multithreader class");
    this.socket = socket;

} // multiThreader

@Override
public void run() {

    System.out.println("multi threader started");

      //================================================================================================
    //==== action #1 read in transfer.pdf file from client ===========================================

    int bufferSize = 0;

    try {

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

     fileSizeFromClient = dis.readInt();
     System.out.println("file size for transfer.pdf from client is " + fileSizeFromClient);

      fileDirectory = new File("C:/DOWNLOAD/");
        if (!fileDirectory.exists()) {
            fileDirectory.mkdir();
      }
     file = new File("C:/DOWNLOAD/transfer.pdf");
      file.createNewFile();

       fos = new FileOutputStream(file);
       bos = new BufferedOutputStream(fos);
       dos = new DataOutputStream(bos);

       byte[] buffer = new byte[fileSizeFromClient];

      int totalBytesRead = 0;

        while(totalBytesRead < fileSizeFromClient){
            int bytesRemaining = fileSizeFromClient - totalBytesRead;
            int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
            if(bytesRead == -1) {
                break;
            } else {
                dos.write(buffer, 0, bytesRead); 
                    totalBytesRead += bytesRead;
            }
        } // while

       // ===================================================================================================== 
       // === action #2 send transfer2.pdf file to client =====================================================

      file = new File("C:/DOWNLOAD/transfer2.pdf");
      file.createNewFile();

      fis = new FileInputStream(file);
      bis = new BufferedInputStream(fis);
      dis = new DataInputStream(bis);
      bos = new BufferedOutputStream(socket.getOutputStream());
      dos = new DataOutputStream(bos);

      length = file.length();

       System.out.println("file size for transfer2.pdf sent to client is " + length);

      dos.writeInt((int) length);

      int count = 0;

      buffer = new byte[(int)length];

      while((count = bis.read(buffer)) > 0){
          bos.write(buffer, 0, count);
      }

           //=====================================================================================
      //=== action #3 read in transferImage.jpg from client =================================

     bufferSize = 0;

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

     fileSizeFromClient = dis.readInt();
     System.out.println("file size for transferImage.jpg from client is " + fileSizeFromClient);

      file = new File("C:/DOWNLOAD/transferImage.jpg");
      file.createNewFile();

       fos = new FileOutputStream(file);
       bos = new BufferedOutputStream(fos);
       dos = new DataOutputStream(bos);

       buffer = new byte[fileSizeFromClient];

       totalBytesRead = 0;

        while(totalBytesRead < fileSizeFromClient){
            int bytesRemaining = fileSizeFromClient - totalBytesRead;
            int bytesRead = dis.read(buffer, 0, (int) Math.min(buffer.length, bytesRemaining));
            if(bytesRead == -1) {
                break;
            } else {
                dos.write(buffer, 0, bytesRead); 
                    totalBytesRead += bytesRead;
            }
        } // while

            //=====================================================================================

      } catch (IOException ex) {
        Logger.getLogger(MultiThreader.class.getName()).log(Level.SEVERE, null, ex);
      }  finally {

                        try {

                                   bis.close();
                                    fis.close();
                                    dis.close();
                                    fos.flush();
                                    fos.close();
                                    bos.flush();
                                    bos.close();
                                    dos.flush();
                                    dos.close();
                                    socket.close();
                                    file = null;
                                    fileDirectory = null;
                                   // System.exit(0);

                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

        }


 } // run

  } // MultiThreader

 public class Server {
 ServerSocket serverSocket;
 Socket socket;
 boolean runner = true;

 Server() throws IOException{

    serverRunner();
    System.out.println("server constructor started");

 } // Server constructor

 public void serverRunner() throws IOException {

    System.out.println("serverrunner started");

     try {

      serverSocket = new ServerSocket(6789, 100);

      runner = true;

        while (runner) {

            socket = serverSocket.accept();

            MultiThreader multi = new MultiThreader(socket);
            Thread t = new Thread(multi);
            t.start();

        }  // while runner
       } catch (IOException ex) {

    }

 } // serverRunner  

 } // class Server

person Kevik    schedule 07.01.2014    source источник
comment
Почему вы строите буферы поверх своего BufferedOutputStream?   -  person Elliott Frisch    schedule 07.01.2014
comment
лучше этого не делать?   -  person Kevik    schedule 07.01.2014
comment
Это бессмысленно; BufferedOutputStream уже выполняет буферизацию... просто записывайте по одному байту за раз и дайте ему разобраться с этим.   -  person Elliott Frisch    schedule 07.01.2014
comment
@ElliottFrisch Но он не читает по одному байту за раз. У него есть массив байтов, поэтому он должен вызвать write(byte[], int, int).. Я согласен, что в данном случае это не обязательно должен быть BufferedOutputStream, но записывать побайтно во что-либо никогда не бывает хорошей идеей.   -  person user207421    schedule 07.01.2014
comment
Я удалил все bufferedOutputSteams и bufferedInputStreams, и он работает так же. поэтому я предполагаю, что если мне не нужны буферизованные потоки, я не буду их использовать в будущем.   -  person Kevik    schedule 07.01.2014


Ответы (1)


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

NB:

  1. Вам не нужен буфер размером всего файла. 8192 подойдет. Ваш код по-прежнему будет работать с любым размером буфера больше нуля.
  2. Вам не нужно вызывать File.createNewFile() перед new FileOutputStream().. Это совершенно избыточно.
person user207421    schedule 07.01.2014