Ошибки ввода-вывода файла Java и ошибки «доступ запрещен» - PullRequest
9 голосов
/ 29 июля 2011

Я рвал на себе волосы, и поэтому мне нужна помощь.

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

//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.IO.error с «access denied» ») не возникает каждый раз ... фактически 60% времени выполнения цикла он не выдает ошибки. Оставшиеся 40% времени я получите ошибку в одном из 60+ записываемых файлов. Нечасто один и тот же. Порядок, в котором начинаются URL-адреса, каждый раз меняется, поэтому порядок записи файлов является переменным. Имена файлов имеют короткие краткие имена, такие как " 1.png ". Изображения маленькие ... если не 8k.

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

Предоставление «полного контроля» ВСЕМ из каталога проекта net beans вниз

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

Отключено UAC

И все же ошибка сохраняется. Поиски в Google, похоже, охватывают всю гамму и часто читаются как vodoo. Очевидно, что я (и Java, и Netbeans и т. Д.) Должен иметь разрешение на запись файла в каталог.

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

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

Обновление 2: Вот одна из трассировок стека (в этом случае для файла file2Save есть перманент R: True W: True E: True isFile: True существующие: 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 ]

1 голос
/ 22 августа 2011

Я не могу сказать вам, что происходит или почему ... У меня такое ощущение, что это что-то зависит от того, как 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), если хотите.Документация здесь .

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

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

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...