Beispiel #1
0
  /**
   * Returns <code>true</code> if the given file exists or can be created and at least one byte can
   * be successfully written to it - the file is restored to its previous state afterwards. This is
   * a much stronger test than {@link File#canWrite()}.
   *
   * <p>Please note that if the file is actually open for reading or other activities this method
   * may not be able to reset the last modification time of the file after testing, in which case
   * <code>false</code> is returned. This is known to apply to the Windows platform, but not on Unix
   * platforms.
   */
  public static boolean isWritableOrCreatable(final java.io.File file) {
    try {
      if (!file.exists()) {
        final boolean created = file.createNewFile();
        boolean ok = isWritableOrCreatable(file);
        if (created && !file.delete()) ok = false; // be conservative!
        return ok;
      } else if (file.canWrite()) {
        // Some operating and file system combinations make File.canWrite()
        // believe that the file is writable although it's not.
        // We are not that gullible, so let's test this...
        final long time = file.lastModified();
        if (!file.setLastModified(time + 1)) {
          // This may happen on Windows and normally means that
          // somebody else has opened this file
          // (regardless of read or write mode).
          // Be conservative: We don't allow writing to this file!
          return false;
        }

        boolean ok;
        try {
          // Open the file for reading and writing, requiring any
          // update to its contents to be written to the filesystem
          // synchronously.
          // As Dr. Simon White from Catalysoft, Cambridge, UK reported,
          // "rws" does NOT work on Mac OS X with Apple's Java 1.5
          // Release 1 (equivalent to Sun's Java 1.5.0_02), however
          // it DOES work with Apple's Java 1.5 Release 3.
          // He also confirmed that "rwd" works on Apple's
          // Java 1.5 Release 1, so we use this instead.
          // Thank you very much for spending the time to fix this
          // issue, Dr. White!
          final RandomAccessFile raf = new RandomAccessFile(file, "rwd");
          try {
            final boolean empty;
            int octet = raf.read();
            if (octet == -1) {
              octet = 0; // assume first byte is 0
              empty = true;
            } else {
              empty = false;
            }

            // Let's test if we can (over)write the first byte.
            raf.seek(0);
            raf.write((octet ^ -1) & 0xFF); // write complement
            try {
              // Rewrite original content and check success.
              raf.seek(0);
              raf.write(octet);
              raf.seek(0);
              final int check = raf.read();
              // This should always return true unless the storage
              // device is faulty.
              ok = octet == check;
            } finally {
              if (empty) raf.setLength(0);
            }
          } finally {
            raf.close();
          }
        } finally {
          if (!file.setLastModified(time)) {
            // This may happen on Windows and normally means that
            // somebody else has opened this file meanwhile
            // (regardless of read or write mode).
            // Be conservative: We don't allow (further) writing to
            // this file!
            ok = false;
          }
        }
        return ok;
      } else { // if (file.exists() && !file.canWrite()) {
        return false;
      }
    } catch (IOException ex) {
      return false; // don't allow writing if anything goes wrong!
    }
  }