Java-файл IO и ошибки "отказано в доступе"

я рвал волосы на этом, и поэтому я ищу некоторую помощь .

у меня есть цикл кода, который выполняет следующее

//imports ommitted
public void afterPropertiesSet() throws Exception{

  //building of URL list ommitted  
  // urlMap is a HashMap <String,String> created and populated just prior   

    for ( Object urlVar : urlMap.keySet() ){
    String myURLvar = urlMap.get(urlVar.toString);
    System.out.println ("URL is "+myURLvar );
    BufferedImage imageVar = ImageIO.read(myURLvar);//URL confirmed to be valid even for executions that fail
    String fileName2Save = "filepath"// a valid file path
    System.out.println ("Target path is "+fileName2Save );
    File file2Save = new File (fileName2Save);
    fileName2Save.SetWriteable(true);//set these just to be sure
    fileName2Save.SetReadable(true);
      try{
       ImageIO.write (imageVar,"png",file2save)//error thrown here 
      }catch (Exception e){
     System.out.println("R: "+file2Save.canRead()+" W: "+file2Save.canWrite()+" E:"+file2Save.canExecute()+" Exists: "+file2Save.exists+" is a file"+file2Save.isFile() );

     System.out.println("parent Directory perms");// same as above except on parent directory of destination
      }//end try
     }//end for
     }

все это работает на Windows 7 и JDK 1.6.26 и Netbeans, Tomcat 7.0.14 . Целевой каталог фактически находится внутри моего каталога проекта netbeans в папке для обычного веб-приложения ( вне WEB-INF), где я ожидал бы, что обычно будет иметь разрешение на запись файлов.

когда возникает ошибка, я получаю один из двух результаты для файла a.) Все ложные b.)все верно. Разрешение родительского каталога никогда не изменяет все true, кроме isFile.

ошибка (java.ИО.ошибка с "Доступ запрещен") не происходит каждый раз ... на самом деле 60% времени выполнения цикла он не выдает ошибок. Оставшиеся 40% времени я получаю ошибку на 1 из 60+ файлов, которые он пишет. Редко один и тот же. Порядок, в котором URL-адреса начинаются с изменений каждый раз, поэтому порядок, в котором файлы записываются переменная. Имена файлов имеют короткие краткие имена, такие как " 1.формат PNG." Изображения небольшие..меньше 8К.

чтобы убедиться, что разрешения правильные, у меня есть:

учитывая "полный контроль" для всех из каталога проекта net beans вниз

запустите JDK, JRE и Netbeans от имени администратора

отключен UAC

тем не менее ошибка сохраняется. Поиск Google для этого, похоже, работает в гамме и часто читается как vodoo. Ясно, что я ( и Java и NetBeans и т. д. ) должны иметь разрешение на запись файла в каталог .

кто-нибудь есть какие-нибудь идеи ? Это все (код и веб-сервер, на котором размещен URL) в закрытой системе, поэтому я не могу вырезать и вставлять код или stacktrace.

Update: я подтвердил, что imageURL действителен, выполнив println & toString перед каждым чтением. Затем я подтвердил, что a.) веб-сервер, на котором размещен целевой URL, вернул изображение с кодом http 200 b.) что URL-адрес вернул изображение, когда проверено в веб-браузере. В тестировании я также поставил if () после чтения, чтобы подтвердить, что значения не были пустыми или пустыми. Я также ввел тесты для NULL для всех других значений . Они всегда таковы, какими их ожидают даже в случае неудачи .Ошибка всегда возникает внутри блока try. Каталог назначения одинаков при каждом выполнении. Перед каждым выполнением каталог пуст.

Update 2: Вот одна из трассировок стека ( в этом случае perms для file2Save - R: True W:True E: True isFile: True exists: True )

    java.io.FileNotFoundException <fullFilepathhere> (Access is denied)
       at java.io.RandomAccessFile.open(Native Method)
       at java.io.RandomAccessFile.<init>(RandomAccessFile.java:212)
       at javax.imageio.stream.FileImageOutputStream.<init>(FileImageOutputStream.java:53)
       at com.sun.imageio.spi.FileImageOutputStreamSpi.createOutputStreamInstance(FileImageOutputStreamSpi.java:37)
       at javax.imageio.ImageIO.createImageOutputStream(ImageIO.java:393)
       at javax.imageio.ImageIO.write(ImageIO.java:1514)
       at myPackage.myClass.afterPropertiesSet(thisClassexample.java:204)// 204 is the line number of the ImageIO write

2 ответов


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

одной из распространенных возможностей для невозможности записи файла в веб-приложении является проблема блокировки файлов в Windows, если одновременно выполняются следующие четыре условия:

  1. целевой файл существует под web root, например и
  2. целевой файл обслуживается сервлетом по умолчанию и
  3. целевого файла был запрошен по крайней мере один раз клиентом и
  4. вы работаете под Windows

Если вы пытаетесь заменить такой файл, который отвечает всем четырем условиям, вы не сможете, потому что некоторые контейнеры сервлетов, такие как tomcat и jetty, будут буферизировать статическое содержимое и блокировать файлы, поэтому вы не сможете их заменить или изменить.

Если ваше веб-приложение имеет именно эту проблему, вы не должны использовать сервлет по умолчанию для обслуживания файла содержание. Сервлет по умолчанию предназначен для обслуживания статического содержимого, которое вы не хотите изменять, например css-файлов, файлов javascript, фоновых изображений и т. д.

существует трюк, чтобы решить проблему блокировки файлов в Windows для причала, отключив NIO http://docs.codehaus.org/display/JETTY/Files + заблокировано + включено + окна

трюк полезен для процесса разработки, например, вы хотите отредактировать файл css и увидеть изменения без перезапуска вашего веб-сайта применение, но не порекомендовано для режима продукции. Если ваше веб-приложение полагается на этот трюк в производственном процессе, вы должны серьезно рассмотреть вопрос о перепроектировании своих кодов.


Я не могу сказать вам, что происходит и почему... У меня такое чувство, что это что-то зависит от пути ImageIO пытается сохранить изображение. Что вы можете сделать, это сохранить BufferedImage используя ByteArrayOutputStream, как описано ниже:

BufferedImage bufferedImage = ImageIO.read(new File("sample_image.gif"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( bufferedImage, "gif", baos );

baos.flush(); //Is this necessary??
byte[] resultImageAsRawBytes = baos.toByteArray();
baos.close(); //Not sure how important this is...

OutputStream out = new FileOutputStream("myImageFile.gif");
out.write(resultImageAsRawBytes);    
out.close();

Я не очень знаком с ByteArrayOutputStream, но я думаю, что его reset() функция может быть удобна при работе с сохранением нескольких файлов. Вы также можете попробовать использовать его writeTo(OutputStream out) если вы предпочитаете. Документация здесь.

Дайте мне знать, как это происходит...