2013-05-05 1 views
0

У меня есть следующий код, который успешно копирует файл. Тем не менее, есть две проблемы, связанные с ним:Блокировка FileInputStream/FileOutputStream?

  1. System.out.println() сразу после progressBar.setValue() не печатает интервалы между 0 и 100 (только печатает «0» до конца, где его prints "100")
  2. Помимо того факта, что значение для индикатора выполнения может быть как-то неправильным из-за вопроса №1, в фактическом коде я делаю другие визуальные изменения, но они не отображаются до тех пор, пока весь файл обрабатывается. Я думал, что функции FileInputStream/FileOutputStream не блокируются. Как я могу изменить следующий код, чтобы индикатор выполнения фактически обновлялся во время операции?

метод StartJob:

private void startJob(File inFile, File outFile) { 
     long offset = 0; 
     int numRead = 0; 
     byte[] bytes = new byte[8192]; 
     long fileLength = inFile.length(); 
     Boolean keepGoing = true; 

     progressBar.setValue(0); 

     try { 
      inputStream = new FileInputStream(inFile); 
      outputStream = new FileOutputStream(outFile, false); 
      System.out.println("Total file size to read (in bytes) : " + inputStream.available()); 
     } catch (FileNotFoundException err) { 
      inputStream = null; 
      outputStream = null; 
      err.printStackTrace(); 
     } catch (IOException err) { 
      inputStream = null; 
      outputStream = null; 
      err.printStackTrace(); 
     } 

     if (inputStream != null && outputStream != null) { 
      while (keepGoing) { 
       try { 
        numRead = inputStream.read(bytes); 
        outputStream.write(bytes, 0, numRead); 
       } catch (IOException err) { 
        keepGoing = false; 
        err.printStackTrace(); 
       } 
       if (numRead > 0) { 
        offset += numRead; 
       } 

       if (offset >= fileLength) { 
        keepGoing = false; 
       } 

       progressBar.setValue(Math.round(offset/fileLength) * 100); 
       System.out.println(Integer.toString(Math.round(offset/fileLength) * 100)); 
      } 
     } 
     if (offset < fileLength) { 
      //error 
     } else { 
      //success 
     } 

     try { 
      inputStream.close(); 
      outputStream.close(); 
     } catch (IOException err) { 
      err.printStackTrace(); 
     } 
    } 
+0

возможный дубликат [JProgressBar обновления не рабочей] (HTTP: // StackOverflow. com/questions/8812718/jprogressbar-update-not-working) –

+1

Вы изучили использование [ProgressMonitorInputStream] (http://docs.oracle.com/javase/7/docs/api/javax/swing/ProgressMonitorInputStream.html)? Это может упростить вам много работы. –

+1

Как FileInputStream не блокирует и все еще возвращает то, что было прочитано? –

ответ

1

Я подозреваю, что вы вызываете свой длинный метод из EDT. Удалите операцию из EDT, поместив его в его собственном Runnable, например, а затем вызвать

SwingUtilities.invokeLater(new Runnable() { 

    @Override 
    public void run() { 
     progressBar.setValue(value); 
     // or any other GUI changes you want to make 
    }  
}); 

В противном случае, ваши операции блокирует EDT до тех пор, пока не будет сделано, и с EDT блокировал нет таких событий, как перекрашивать и т.д. будут могут быть обработано -> никаких изменений GUI не видно до конца.

1

Значение выражения Math.round(offset/fileLength) будет равно 0 (ноль), так как offset < fileLength.

UPD:

Если вы хотите сделать этот расчет правильно, вы должны изменить его на:

Math.round(((double)offset/(double)fileLength) * 100)