JDK

java.io.UncheckedIOException

UncheckedIOExceptionクラスは非チェック例外のIO例外で,Java8から導入されたようだ。IOExceptionはチェック例外であるため,IOExceptionがスローされるメソッドにはthrowsをつけて宣言するか,内部でcatchする必要がある。これを回避できるようにしたものが,このUncheckedIOExceptionクラスで,非チェック例外であるRuntimeExceptionクラスを継承している。

コンストラクタは次の2つがオーバーロードされており,いずれも引数にIOExceptionをとる。しかも,内部でObjects.requireNonNull(cause)が呼ばれているため,nullを渡すことも許されない。従って,IOExceptionクラスのインスタンスがないと,UncheckedIOExceptionクラスのインスタンスを作ることができない。IOExceptionをラップして非チェック例外にするためのラッパークラスと言える。
  • UncheckedIOException(String message, IOException cause)
  • UncheckedIOException(IOException cause)
/*
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.util.Objects;
public class UncheckedIOException extends RuntimeException {
    private static final long serialVersionUID = -8134305061645241065L;
    public UncheckedIOException(String message, IOException cause) {
        super(message, Objects.requireNonNull(cause));
    }
    public UncheckedIOException(IOException cause) {
        super(Objects.requireNonNull(cause));
    }
    @Override
    public IOException getCause() {
        return (IOException) super.getCause();
    }
    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException
    {
        s.defaultReadObject();
        Throwable cause = super.getCause();
        if (!(cause instanceof IOException))
            throw new InvalidObjectException("Cause must be an IOException");
    }
}
JDK

java.io.OutputStreamWriterクラス

OutputStreamWriterクラスはOutputStreamに対して書き込むためのWriterクラスである。java.io.Writerクラスを継承している。インスタンス変数として,sun.nio.cs.StreamEncoderというクラスが使われており,このクラスでエンコードしていると思われる。

コンストラクタとしては,次のようなものが定義されている。
  • OutputStreamWriter(OutputStream out, String charsetName)
  • OutputStreamWriter(OutputStream out)
  • OutputStreamWriter(OutputStream out, Charset cs)
  • OutputStreamWriter(OutputStream out, CharsetEncoder enc)

write(int c)メソッドはOutputStreamに対して,int型の引数で与えられた文字1文字を書き込む。write(char cbuf[], int off, int len)メソッドはchar[]型の引数で与えられた配列の指定のオフセットから指定の長さだけOutputStreamに書き込む。write(String str, int off, int len)メソッドはchar[]型配列の代わりにString型のオブジェクトを書き込む。

append(CharSequence csq, int start, int end)メソッドは CharSequence インタフェースを実装したオブジェクトのインデックスstartからendまでを切り出して,追加する。append(CharSequence csq)メソッドはそのまま引数で与えられたオブジェクトを追加してOutputStreamへ書き込む。

/*
 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the “Classpath” exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import sun.nio.cs.StreamEncoder;
public class OutputStreamWriter extends Writer {
    private final StreamEncoder se;
    public OutputStreamWriter(OutputStream out, String charsetName)
        throws UnsupportedEncodingException
    {
        super(out);
        if (charsetName == null)
            throw new NullPointerException(“charsetName”);
        se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
    }
    public OutputStreamWriter(OutputStream out) {
        super(out);
        try {
            se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
        } catch (UnsupportedEncodingException e) {
            throw new Error(e);
        }
    }
    public OutputStreamWriter(OutputStream out, Charset cs) {
        super(out);
        if (cs == null)
            throw new NullPointerException(“charset”);
        se = StreamEncoder.forOutputStreamWriter(out, this, cs);
    }
    public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
        super(out);
        if (enc == null)
            throw new NullPointerException(“charset encoder”);
        se = StreamEncoder.forOutputStreamWriter(out, this, enc);
    }
    public String getEncoding() {
        return se.getEncoding();
    }
    void flushBuffer() throws IOException {
        se.flushBuffer();
    }
    public void write(int c) throws IOException {
        se.write(c);
    }
    public void write(char cbuf[], int off, int len) throws IOException {
        se.write(cbuf, off, len);
    }
    public void write(String str, int off, int len) throws IOException {
        se.write(str, off, len);
    }
    @Override
    public Writer append(CharSequence csq, int start, int end) throws IOException {
        if (csq == null) csq = “null”;
        return append(csq.subSequence(start, end));
    }
    @Override
    public Writer append(CharSequence csq) throws IOException {
        if (csq instanceof CharBuffer) {
            se.write((CharBuffer) csq);
        } else {
            se.write(String.valueOf(csq));
        }
        return this;
    }
    public void flush() throws IOException {
        se.flush();
    }
    public void close() throws IOException {
        se.close();
    }
}
JDK

java.io.InputStreamReaderクラス

InputStreamReaderクラスはInputStreamからデータを読み込むためのクラスであり,Readerクラスを継承している。privateなインスタンス変数として定義されているsun. nio. cs. StreamDecoderクラスを用いてデコードしている。

コンストラクタとしては,以下のようなものがオーバーロードされている。
  • InputStreamReader(InputStream in)
  • InputStreamReader(InputStream in, String charsetName)
  • InputStreamReader(InputStream in, Charset cs)
  • InputStreamReader(InputStream in, CharsetDecoder dec)

read()メソッドでは,InputStreamから1文字読込んで,int型で返す。read(char cbuf[], int offset, int length)メソッドはchar[]型の配列へ指定のオフセットから指定の長さだけ読み込んで返す。

/*
 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import sun.nio.cs.StreamDecoder;
public class InputStreamReader extends Reader {
    private final StreamDecoder sd;
    public InputStreamReader(InputStream in) {
        super(in);
        try {
            sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
        } catch (UnsupportedEncodingException e) {
            // The default encoding should always be available
            throw new Error(e);
        }
    }
    public InputStreamReader(InputStream in, String charsetName)
        throws UnsupportedEncodingException
    {
        super(in);
        if (charsetName == null)
            throw new NullPointerException("charsetName");
        sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
    }
    public InputStreamReader(InputStream in, Charset cs) {
        super(in);
        if (cs == null)
            throw new NullPointerException("charset");
        sd = StreamDecoder.forInputStreamReader(in, this, cs);
    }
    public InputStreamReader(InputStream in, CharsetDecoder dec) {
        super(in);
        if (dec == null)
            throw new NullPointerException("charset decoder");
        sd = StreamDecoder.forInputStreamReader(in, this, dec);
    }
    public String getEncoding() {
        return sd.getEncoding();
    }
    public int read() throws IOException {
        return sd.read();
    }
    public int read(char cbuf[], int offset, int length) throws IOException {
        return sd.read(cbuf, offset, length);
    }
    public boolean ready() throws IOException {
        return sd.ready();
    }
    public void close() throws IOException {
        sd.close();
    }
}

JDK

java.io.StringWriterクラス

StringWriterクラスは文字列に対してStreamのように書き込めるようにしたクラスである。内部では,StringBuffer型のインスタンス変数bufにデータを保持している。

コンストラクタは次のようなものがオーバーロードされている。2つめのコンストラクタは内部のバッファサイズを指定できる。
  • StringWriter()
  • StringWriter(int initialSize)

write(int c)メソッドはバッファに対してint型で与えられたコードに対応する文字を追加して書き込む。write(char cbuf[], int off, int len)write(int c)メソッドはバッファに対してchar[]型で与えられた文字配列を指定のオフセットから長さ分だけ追加する。write(String str)メソッドはString型の文字列をバッファに追加する。write(String str, int off, int len)メソッドはString型の文字列を指定のオフセットから指定の長さだけバッファに追加する。

append(CharSequence csq)メソッドは引数のCharSequence(StringやStringBufferが実装しているインタフェースでcharのシーケンスを保持している)を追加し,自身のインスタンスを返す。append(CharSequence csq, int start, int end)メソッドは引数のCharSequenceにおける指定の開始位置から終了位置までの部分を取り出してバッファへ追加し,自身のオブジェクトを返す。append(char c)は文字をバッファに追加し,自身をオブジェクトを返す。getBuffer()メソッドはこのクラスのバッファとなっているStringBufferインスタンス変数への参照を返す。

flush()メソッドとclose()メソッドは何も実行しない。

/*
 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
public class StringWriter extends Writer {
    private StringBuffer buf;
    public StringWriter() {
        buf = new StringBuffer();
        lock = buf;
    }
    public StringWriter(int initialSize) {
        if (initialSize < 0) {
            throw new IllegalArgumentException("Negative buffer size");
        }
        buf = new StringBuffer(initialSize);
        lock = buf;
    }
    public void write(int c) {
        buf.append((char) c);
    }
    public void write(char cbuf[], int off, int len) {
        if ((off < 0) || (off > cbuf.length) || (len < 0) ||
            ((off + len) > cbuf.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        buf.append(cbuf, off, len);
    }
    public void write(String str) {
        buf.append(str);
    }
    public void write(String str, int off, int len)  {
        buf.append(str, off, off + len);
    }
    public StringWriter append(CharSequence csq) {
        write(String.valueOf(csq));
        return this;
    }
    public StringWriter append(CharSequence csq, int start, int end) {
        if (csq == null) csq = "null";
        return append(csq.subSequence(start, end));
    }
    public StringWriter append(char c) {
        write(c);
        return this;
    }
    public String toString() {
        return buf.toString();
    }
    public StringBuffer getBuffer() {
        return buf;
    }
    public void flush() {
    }
    public void close() throws IOException {
    }
}
JDK

java.io.StringReaderクラス

StringReaderクラスはStringをストリームのように扱うためのクラスである。

インスタンス変数として,次の4つが定義されている。strは読み込む対象の文字列である。lengthはstrの長さを示す。nextは次に読み込む位置を表すインデックスである。markはreset()メソッドを実行した際に戻るべき位置のインデックスを表す。
  • String str
  • int length
  • int next
  • int mark

コンストラクタはStringReader(String s)のみが定義されており,引数に読み込む対象の文字列を渡す。

read()メソッドは対象文字列からnext変数で示された位置のバイトを読込み,int型に格納して返す。そして,next変数を1増加させる。read(char cbuf[], int off, int len)read()メソッドは対象文字列から指定のオフセットと長さだけ読込み,byte[]型の引数bufに格納して返す。skip(long)メソッドは指定されたバイト数だけ読み込む位置をスキップする。mark(int readAheadLimit)メソッドは,指定の位置にマークを設定し,reset()メソッドが呼ばれた際に戻る位置を設定する。reset()メソッドでは,next変数にmark変数の内容を設定し,markの位置から読み込むように状態を変化させる。close()メソッドは,インスタンス変数strにnullをセットしているだけである。

/*
 * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
public class StringReader extends Reader {
    private String str;
    private int length;
    private int next = 0;
    private int mark = 0;
    public StringReader(String s) {
        this.str = s;
        this.length = s.length();
    }
    private void ensureOpen() throws IOException {
        if (str == null)
            throw new IOException("Stream closed");
    }
    public int read() throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (next >= length)
                return -1;
            return str.charAt(next++);
        }
    }
    public int read(char cbuf[], int off, int len) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
                ((off + len) > cbuf.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
            if (next >= length)
                return -1;
            int n = Math.min(length – next, len);
            str.getChars(next, next + n, cbuf, off);
            next += n;
            return n;
        }
    }
    public long skip(long ns) throws IOException {
        synchronized (lock) {
            ensureOpen();
            if (next >= length)
                return 0;
            // Bound skip by beginning and end of the source
            long n = Math.min(length – next, ns);
            n = Math.max(-next, n);
            next += n;
            return n;
        }
    }
    public boolean ready() throws IOException {
        synchronized (lock) {
            ensureOpen();
            return true;
        }
    }
    public boolean markSupported() {
        return true;
    }
    public void mark(int readAheadLimit) throws IOException {
        if (readAheadLimit < 0){
            throw new IllegalArgumentException("Read-ahead limit < 0");
        }
        synchronized (lock) {
            ensureOpen();
            mark = next;
        }
    }
    public void reset() throws IOException {
        synchronized (lock) {
            ensureOpen();
            next = mark;
        }
    }
    public void close() {
        synchronized (lock) {
            str = null;
        }
    }
}
JDK

java.io.FileWriterクラス

FileWriterクラスはOutputStreamWriterクラスを継承したクラスで,ファイルに書き込むストリームを提供する。

 コンストラクタは,以下のような多くの種類がオーバーロードされている。このクラスで独自に実装されているメソッドはなく,すべてスーパークラスのメソッドを継承する。
  • FileWriter(String fileName)
  • FileWriter(String fileName, boolean append)
  • FileWriter(File file)
  • FileWriter(File file, boolean append)
  • FileWriter(FileDescriptor fd)
  • FileWriter(String fileName, Charset charset)
  • FileWriter(String fileName, Charset charset, boolean append)
  • FileWriter(File file, Charset charset)
  • FileWriter(File file, Charset charset, boolean append)
/*
 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.nio.charset.Charset;
public class FileWriter extends OutputStreamWriter {
    public FileWriter(String fileName) throws IOException {
        super(new FileOutputStream(fileName));
    }
    public FileWriter(String fileName, boolean append) throws IOException {
        super(new FileOutputStream(fileName, append));
    }
    public FileWriter(File file) throws IOException {
        super(new FileOutputStream(file));
    }
    public FileWriter(File file, boolean append) throws IOException {
        super(new FileOutputStream(file, append));
    }
    public FileWriter(FileDescriptor fd) {
        super(new FileOutputStream(fd));
    }
    public FileWriter(String fileName, Charset charset) throws IOException {
        super(new FileOutputStream(fileName), charset);
    }
    public FileWriter(String fileName, Charset charset, boolean append) throws IOException {
        super(new FileOutputStream(fileName, append), charset);
    }
    public FileWriter(File file, Charset charset) throws IOException {
        super(new FileOutputStream(file), charset);
    }
    public FileWriter(File file, Charset charset, boolean append) throws IOException {
        super(new FileOutputStream(file, append), charset);
    }
}
JDK

java.io.FileReaderクラス

FileReaderクラスはInputStreamReaderのサブクラスであり,ファイルからその内容を読み込む。

以下のようなコンストラクタが定義されている。このクラスではコンストラクタのみが定義されており,メソッドは定義されていない。

  • FileReader(String fileName)
  • FileReader(File file)
  • FileReader(FileDescriptor fd)
  • FileReader(String fileName, Charset charset)
  • FileReader(File file, Charset charset)

/*
 * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.nio.charset.Charset;
public class FileReader extends InputStreamReader {
    public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }
    public FileReader(File file) throws FileNotFoundException {
        super(new FileInputStream(file));
    }
    public FileReader(FileDescriptor fd) {
        super(new FileInputStream(fd));
    }
    public FileReader(String fileName, Charset charset) throws IOException {
        super(new FileInputStream(fileName), charset);
    }
    public FileReader(File file, Charset charset) throws IOException {
        super(new FileInputStream(file), charset);
    }
}
JDK

java.io.FileSystemクラス

FileSystemクラスは様々なファイルシステムを扱うための抽象クラスで,publicなメソッドは宣言のみである。実装はそれぞれのファイルシステムに対応するサブクラスで行われる。仕様についてはAPIドキュメントを参照して頂きたい。

/*
 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.io;
import java.lang.annotation.Native;
abstract class FileSystem {
    /* — Normalization and construction — */
    public abstract char getSeparator();
    public abstract char getPathSeparator();
    public abstract String normalize(String path);
    public abstract int prefixLength(String path);
    public abstract String resolve(String parent, String child);
    public abstract String getDefaultParent();
    public abstract String fromURIPath(String path);
    /* — Path operations — */
    public abstract boolean isAbsolute(File f);
    public abstract String resolve(File f);
    public abstract String canonicalize(String path) throws IOException;
    /* — Attribute accessors — */
    /* Constants for simple boolean attributes */
    @Native public static final int BA_EXISTS    = 0x01;
    @Native public static final int BA_REGULAR   = 0x02;
    @Native public static final int BA_DIRECTORY = 0x04;
    @Native public static final int BA_HIDDEN    = 0x08;
    public abstract int getBooleanAttributes(File f);
    @Native public static final int ACCESS_READ    = 0x04;
    @Native public static final int ACCESS_WRITE   = 0x02;
    @Native public static final int ACCESS_EXECUTE = 0x01;
    public abstract boolean checkAccess(File f, int access);
    public abstract boolean setPermission(File f, int access, boolean enable, boolean owneronly);
    public abstract long getLastModifiedTime(File f);
    public abstract long getLength(File f);
    /* — File operations — */
    public abstract boolean createFileExclusively(String pathname)
        throws IOException;
    public abstract boolean delete(File f);
    public abstract String[] list(File f);
    public abstract boolean createDirectory(File f);
    public abstract boolean rename(File f1, File f2);
    public abstract boolean setLastModifiedTime(File f, long time);
    public abstract boolean setReadOnly(File f);
    /* — Filesystem interface — */
    public abstract File[] listRoots();
    /* — Disk usage — */
    @Native public static final int SPACE_TOTAL  = 0;
    @Native public static final int SPACE_FREE   = 1;
    @Native public static final int SPACE_USABLE = 2;
    public abstract long getSpace(File f, int t);
    /* — Basic infrastructure — */
    public abstract int getNameMax(String path);
    public abstract int compare(File f1, File f2);
    public abstract int hashCode(File f);
    // Flags for enabling/disabling performance optimizations for file
    // name canonicalization
    static final boolean useCanonCaches;
    static final boolean useCanonPrefixCache;
    private static boolean getBooleanProperty(String prop, boolean defaultVal) {
        String value = System.getProperty(prop);
        return (value != null) ? Boolean.parseBoolean(value) : defaultVal;
    }
    static {
        useCanonCaches      = getBooleanProperty("sun.io.useCanonCaches", false);
        useCanonPrefixCache = useCanonCaches && getBooleanProperty("sun.io.useCanonPrefixCache", false);
    }
}
未分類

UPS(無停電電源装置)バッテリー交換

 UPSのバッテリー劣化を知らせる警報が作動したため,バッテリーを交換しました。電源を入れたまま交換できるのはありがたいですね。古いバッテリーは自治体では回収してくれないので,メーカーへ送って処分してもらいます。鉛,硫酸など,危険物がいっぱい入っているから仕方ないですね。

 メーカーの製品ページはこちら。

https://www.oss.omron.co.jp/ups/product/by35-120s/by35-120s.html

 古いバッテリーを送ろうとしたら,けっこう大変でした。郵便局のコールセンターに問い合わせると,「鉛電池は禁制品になっている」と断られました。ヤマト運輸のWebにもバッテリーは不可と書いてありました。昨日新品のバッテリーを持ってきてくれた佐川急便なら拒否しないだろうと思い,問い合わせてみると,密閉容器に入っているものならOKだが,今日は集荷できないとのこと。バスに乗って佐川急便の配送拠点へ持込みました。

バッテリ交換ランプが点灯(ブザーもなっていたが停めた)
交換用のあたらしいバッテリ
UPSを開けたところ
JDK

java.io.Fileクラス

Fileクラスは古くからファイルシステム上のディレクトリやファイルを扱うクラスとして非常によく使われてきたものである。元のソースコードは2000行を超える巨大なものになっている。

 インスタンス変数としては,次のようなものが定義されている。

  • fs ローカルのファイルシステム
  • path 対象のディレクトリやファイルのパス文字列
  • status パスの状態を表すenum値(有効/無効)
  • separatorChar 区切り文字(Windowsは’\’,LinuxやMacOSでは’/’)
  • separator 区切り文字列
  • pathSeparatorChar 複数のパスを表す際の区切り文字(Windowsは’;’,LinuxやMacOSは’:’)
  • separator 複数のパスを表す際の区切り文字列

 publicなコンストラクタとしては,以下のようなものがオーバーロードされている。

  • File(String pathname)
  • File(String parent, String child)
  • File(File parent, String child)
  • File(URI uri)
  •  getName()メソッドは,ディレクトリ,または,ファイルの名前のみを取得するメソッドである。path文字列から,lastIndexOf(separatorChar)で最後の区切文字の位置を探し出して,それ以降の部分文字列を切り出している。getParent()メソッドはこれと逆の操作をすることで,親ディレクトリのパスを取得している。

    privateなメソッドであるが,slashify(String path, boolean isDirectory)メソッドは注目に価する。区切り文字が’/’ではない場合,すなわち,Windowsの場合,は区切り文字を’/’に変換したパス文字列を返す。このようにしてJavaはOSの違いを吸収しているようだ。

    canRead()メソッド,canWrite()メソッド,canExecute() メソッドはSecurityManagerクラスを使って,それぞれ,そのパスに対する読取権限,書込権限,実行権限があるかチェックする。

    exists()メソッドはディレクトリ,あるいは,ファイルが存在するかどうかをチェックするものである。isDirectory()メソッドは表しているオブジェクトがディレクトリであるかどうかをチェックする。isFile()メソッドは,表しているオブジェクトがファイルであるかどうかをチェックする。isHidden()メソッドは表しているオブジェクトが所謂「隠しファイル/ディレクトリ」であるかどうかをチェックする。

    lastModified()メソッドではファイルが最後に更新されたタイムスタンプをlong型で返す。length()メソッドではファイルサイズをlong型で返す。

    createNewFile()メソッドは,ファイルを新しく作成する。delete()メソッドはファイルを削除する。deleteOnExit()メソッドはプロセス終了時にファイルを削除させるフックメソッドであり,DeleteOnExitHook.add(path)を実行して,プロセス終了時の削除対象にパスを登録する。mkdir()メソッドはディレクトリを作成する。mkdirs()メソッドは,存在しない親ディレクトリも作成した上でディレクトリを一度に作成する。

    list()メソッドはディレクトリ内のサブディレクトリまたはファイルをString[]型で返す。list(FilenameFilter filter)メソッドは,ディレクトリ内のファイルのうち,filterで指定された条件に当てはまるものだけをString[]型で返す。

    listFiles()メソッドもlist()メソッドと同様の処理を行う(内部でlist()メソッドを呼んでいる)が,戻り値型がFileクラスの配列である点が異なる。listFiles( FilenameFilter filter )メソッドも同様である。listFiles( FileFilter filter)メソッドは引数のフィルタリングのためのクラスが異なる。

    renameTo(File dest)メソッドは対象のディレクトリ,または,ファイルの名称を変更する。setLastModified(long time)は最終更新のタイムスタンプを変更する。setReadOnly()メソッドは,読取専用の設定を行う。setWritable(boolean writable, boolean ownerOnly)メソッドは書込権限の設定を行う。2つ目の引数はファイルのオーナーのみ書込ができるようにするフラグである。setWritable(boolean writable)メソッドは書込権をセットするもので,内部ではsetWritable(writable, true)を呼び出している。setReadable(boolean readable, boolean ownerOnly)メソッドとsetReadable(boolean readable)メソッドは読込権限について同様のことを行う。setExecutable(boolean executable, boolean ownerOnly)メソッドとsetExecutable(boolean executable)メソッドは実行権限について,同様のことを行う。

    /*
     * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     *
     * This code is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 only, as
     * published by the Free Software Foundation.  Oracle designates this
     * particular file as subject to the "Classpath" exception as provided
     * by Oracle in the LICENSE file that accompanied this code.
     *
     * This code is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     * version 2 for more details (a copy is included in the LICENSE file that
     * accompanied this code).
     *
     * You should have received a copy of the GNU General Public License version
     * 2 along with this work; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     * or visit www.oracle.com if you need additional information or have any
     * questions.
     */
    package java.io;
    import java.net.URI;
    import java.net.URL;
    import java.net.MalformedURLException;
    import java.net.URISyntaxException;
    import java.nio.file.FileSystems;
    import java.nio.file.Path;
    import java.security.SecureRandom;
    import java.util.ArrayList;
    import java.util.List;
    import sun.security.action.GetPropertyAction;
    public class File
        implements Serializable, Comparable<File>
    {
        private static final FileSystem fs = DefaultFileSystem.getFileSystem();
        private final String path;
        private static enum PathStatus { INVALID, CHECKED };
        private transient PathStatus status = null;
        final boolean isInvalid() {
            if (status == null) {
                status = (this.path.indexOf('\u0000') < 0) ? PathStatus.CHECKED
                                                           : PathStatus.INVALID;
            }
            return status == PathStatus.INVALID;
        }
        private final transient int prefixLength;
        int getPrefixLength() {
            return prefixLength;
        }
        public static final char separatorChar = fs.getSeparator();
        public static final String separator = "" + separatorChar;
        public static final char pathSeparatorChar = fs.getPathSeparator();
        public static final String pathSeparator = "" + pathSeparatorChar;
        /* — Constructors — */
        private File(String pathname, int prefixLength) {
            this.path = pathname;
            this.prefixLength = prefixLength;
        }
        private File(String child, File parent) {
            assert parent.path != null;
            assert (!parent.path.isEmpty());
            this.path = fs.resolve(parent.path, child);
            this.prefixLength = parent.prefixLength;
        }
        public File(String pathname) {
            if (pathname == null) {
                throw new NullPointerException();
            }
            this.path = fs.normalize(pathname);
            this.prefixLength = fs.prefixLength(this.path);
        }
        /* Note: The two-argument File constructors do not interpret an empty
           parent abstract pathname as the current user directory.  An empty parent
           instead causes the child to be resolved against the system-dependent
           directory defined by the FileSystem.getDefaultParent method.  On Unix
           this default is "/", while on Microsoft Windows it is "\\".  This is required for
           compatibility with the original behavior of this class. */
        public File(String parent, String child) {
            if (child == null) {
                throw new NullPointerException();
            }
            if (parent != null) {
                if (parent.isEmpty()) {
                    this.path = fs.resolve(fs.getDefaultParent(),
                                           fs.normalize(child));
                } else {
                    this.path = fs.resolve(fs.normalize(parent),
                                           fs.normalize(child));
                }
            } else {
                this.path = fs.normalize(child);
            }
            this.prefixLength = fs.prefixLength(this.path);
        }
        public File(File parent, String child) {
            if (child == null) {
                throw new NullPointerException();
            }
            if (parent != null) {
                if (parent.path.isEmpty()) {
                    this.path = fs.resolve(fs.getDefaultParent(),
                                           fs.normalize(child));
                } else {
                    this.path = fs.resolve(parent.path,
                                           fs.normalize(child));
                }
            } else {
                this.path = fs.normalize(child);
            }
            this.prefixLength = fs.prefixLength(this.path);
        }
        public File(URI uri) {
            // Check our many preconditions
            if (!uri.isAbsolute())
                throw new IllegalArgumentException("URI is not absolute");
            if (uri.isOpaque())
                throw new IllegalArgumentException("URI is not hierarchical");
            String scheme = uri.getScheme();
            if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
                throw new IllegalArgumentException("URI scheme is not \"file\"");
            if (uri.getRawAuthority() != null)
                throw new IllegalArgumentException("URI has an authority component");
            if (uri.getRawFragment() != null)
                throw new IllegalArgumentException("URI has a fragment component");
            if (uri.getRawQuery() != null)
                throw new IllegalArgumentException("URI has a query component");
            String p = uri.getPath();
            if (p.isEmpty())
                throw new IllegalArgumentException("URI path component is empty");
            // Okay, now initialize
            p = fs.fromURIPath(p);
            if (File.separatorChar != '/')
                p = p.replace('/', File.separatorChar);
            this.path = fs.normalize(p);
            this.prefixLength = fs.prefixLength(this.path);
        }
        /* — Path-component accessors — */
        public String getName() {
            int index = path.lastIndexOf(separatorChar);
            if (index < prefixLength) return path.substring(prefixLength);
            return path.substring(index + 1);
        }
        public String getParent() {
            int index = path.lastIndexOf(separatorChar);
            if (index < prefixLength) {
                if ((prefixLength > 0) && (path.length() > prefixLength))
                    return path.substring(0, prefixLength);
                return null;
            }
            return path.substring(0, index);
        }
        public File getParentFile() {
            String p = this.getParent();
            if (p == null) return null;
            return new File(p, this.prefixLength);
        }
        public String getPath() {
            return path;
        }
        /* — Path operations — */
        public boolean isAbsolute() {
            return fs.isAbsolute(this);
        }
        public String getAbsolutePath() {
            return fs.resolve(this);
        }
        public File getAbsoluteFile() {
            String absPath = getAbsolutePath();
            return new File(absPath, fs.prefixLength(absPath));
        }
        public String getCanonicalPath() throws IOException {
            if (isInvalid()) {
                throw new IOException("Invalid file path");
            }
            return fs.canonicalize(fs.resolve(this));
        }
        public File getCanonicalFile() throws IOException {
            String canonPath = getCanonicalPath();
            return new File(canonPath, fs.prefixLength(canonPath));
        }
        private static String slashify(String path, boolean isDirectory) {
            String p = path;
            if (File.separatorChar != '/')
                p = p.replace(File.separatorChar, '/');
            if (!p.startsWith("/"))
                p = "/" + p;
            if (!p.endsWith("/") && isDirectory)
                p = p + "/";
            return p;
        }
        @Deprecated
        public URL toURL() throws MalformedURLException {
            if (isInvalid()) {
                throw new MalformedURLException("Invalid file path");
            }
            return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
        }
        public URI toURI() {
            try {
                File f = getAbsoluteFile();
                String sp = slashify(f.getPath(), f.isDirectory());
                if (sp.startsWith("//"))
                    sp = "//" + sp;
                return new URI("file", null, sp, null);
            } catch (URISyntaxException x) {
                throw new Error(x);         // Can't happen
            }
        }
        /* — Attribute accessors — */
        public boolean canRead() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.checkAccess(this, FileSystem.ACCESS_READ);
        }
        public boolean canWrite() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.checkAccess(this, FileSystem.ACCESS_WRITE);
        }
        public boolean exists() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return false;
            }
            return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
        }
        public boolean isDirectory() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return false;
            }
            return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
                    != 0);
        }
        public boolean isFile() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return false;
            }
            return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
        }
        public boolean isHidden() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return false;
            }
            return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
        }
        public long lastModified() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return 0L;
            }
            return fs.getLastModifiedTime(this);
        }
        public long length() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return 0L;
            }
            return fs.getLength(this);
        }
        /* — File operations — */
        public boolean createNewFile() throws IOException {
            SecurityManager security = System.getSecurityManager();
            if (security != null) security.checkWrite(path);
            if (isInvalid()) {
                throw new IOException("Invalid file path");
            }
            return fs.createFileExclusively(path);
        }
        public boolean delete() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkDelete(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.delete(this);
        }
        public void deleteOnExit() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkDelete(path);
            }
            if (isInvalid()) {
                return;
            }
            DeleteOnExitHook.add(path);
        }
        public String[] list() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(path);
            }
            if (isInvalid()) {
                return null;
            }
            return fs.list(this);
        }
        public String[] list(FilenameFilter filter) {
            String names[] = list();
            if ((names == null) || (filter == null)) {
                return names;
            }
            List<String> v = new ArrayList<>();
            for (int i = 0 ; i < names.length ; i++) {
                if (filter.accept(this, names[i])) {
                    v.add(names[i]);
                }
            }
            return v.toArray(new String[v.size()]);
        }
        public File[] listFiles() {
            String[] ss = list();
            if (ss == null) return null;
            int n = ss.length;
            File[] fs = new File[n];
            for (int i = 0; i < n; i++) {
                fs[i] = new File(ss[i], this);
            }
            return fs;
        }
        public File[] listFiles(FilenameFilter filter) {
            String ss[] = list();
            if (ss == null) return null;
            ArrayList<File> files = new ArrayList<>();
            for (String s : ss)
                if ((filter == null) || filter.accept(this, s))
                    files.add(new File(s, this));
            return files.toArray(new File[files.size()]);
        }
        public File[] listFiles(FileFilter filter) {
            String ss[] = list();
            if (ss == null) return null;
            ArrayList<File> files = new ArrayList<>();
            for (String s : ss) {
                File f = new File(s, this);
                if ((filter == null) || filter.accept(f))
                    files.add(f);
            }
            return files.toArray(new File[files.size()]);
        }
        public boolean mkdir() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.createDirectory(this);
        }
        public boolean mkdirs() {
            if (exists()) {
                return false;
            }
            if (mkdir()) {
                return true;
            }
            File canonFile = null;
            try {
                canonFile = getCanonicalFile();
            } catch (IOException e) {
                return false;
            }
            File parent = canonFile.getParentFile();
            return (parent != null && (parent.mkdirs() || parent.exists()) &&
                    canonFile.mkdir());
        }
        public boolean renameTo(File dest) {
            if (dest == null) {
                throw new NullPointerException();
            }
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
                security.checkWrite(dest.path);
            }
            if (this.isInvalid() || dest.isInvalid()) {
                return false;
            }
            return fs.rename(this, dest);
        }
        public boolean setLastModified(long time) {
            if (time < 0) throw new IllegalArgumentException("Negative time");
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.setLastModifiedTime(this, time);
        }
        public boolean setReadOnly() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.setReadOnly(this);
        }
        public boolean setWritable(boolean writable, boolean ownerOnly) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
        }
        public boolean setWritable(boolean writable) {
            return setWritable(writable, true);
        }
        public boolean setReadable(boolean readable, boolean ownerOnly) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
        }
        public boolean setReadable(boolean readable) {
            return setReadable(readable, true);
        }
        public boolean setExecutable(boolean executable, boolean ownerOnly) {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkWrite(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
        }
        public boolean setExecutable(boolean executable) {
            return setExecutable(executable, true);
        }
        public boolean canExecute() {
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkExec(path);
            }
            if (isInvalid()) {
                return false;
            }
            return fs.checkAccess(this, FileSystem.ACCESS_EXECUTE);
        }
        /* — Filesystem interface — */
        public static File[] listRoots() {
            return fs.listRoots();
        }
        /* — Disk usage — */
        public long getTotalSpace() {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
                sm.checkRead(path);
            }
            if (isInvalid()) {
                return 0L;
            }
            return fs.getSpace(this, FileSystem.SPACE_TOTAL);
        }
        public long getFreeSpace() {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
                sm.checkRead(path);
            }
            if (isInvalid()) {
                return 0L;
            }
            return fs.getSpace(this, FileSystem.SPACE_FREE);
        }
        public long getUsableSpace() {
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                sm.checkPermission(new RuntimePermission("getFileSystemAttributes"));
                sm.checkRead(path);
            }
            if (isInvalid()) {
                return 0L;
            }
            return fs.getSpace(this, FileSystem.SPACE_USABLE);
        }
        /* — Temporary files — */
        private static class TempDirectory {
            private TempDirectory() { }
            // temporary directory location
            private static final File tmpdir = new File(
                    GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
            static File location() {
                return tmpdir;
            }
            // file name generation
            private static final SecureRandom random = new SecureRandom();
            private static int shortenSubName(int subNameLength, int excess,
                int nameMin) {
                int newLength = Math.max(nameMin, subNameLength – excess);
                if (newLength < subNameLength) {
                    return newLength;
                }
                return subNameLength;
            }
            static File generateFile(String prefix, String suffix, File dir)
                throws IOException
            {
                long n = random.nextLong();
                String nus = Long.toUnsignedString(n);
                // Use only the file name from the supplied prefix
                prefix = (new File(prefix)).getName();
                int prefixLength = prefix.length();
                int nusLength = nus.length();
                int suffixLength = suffix.length();;
                String name;
                int nameMax = fs.getNameMax(dir.getPath());
                int excess = prefixLength + nusLength + suffixLength – nameMax;
                if (excess <= 0) {
                    name = prefix + nus + suffix;
                } else {
                    // Name exceeds the maximum path component length: shorten it
                    // Attempt to shorten the prefix length to no less then 3
                    prefixLength = shortenSubName(prefixLength, excess, 3);
                    excess = prefixLength + nusLength + suffixLength – nameMax;
                    if (excess > 0) {
                        // Attempt to shorten the suffix length to no less than
                        // 0 or 4 depending on whether it begins with a dot ('.')
                        suffixLength = shortenSubName(suffixLength, excess,
                            suffix.indexOf(".") == 0 ? 4 : 0);
                        suffixLength = shortenSubName(suffixLength, excess, 3);
                        excess = prefixLength + nusLength + suffixLength – nameMax;
                    }
                    if (excess > 0 && excess <= nusLength – 5) {
                        // Attempt to shorten the random character string length
                        // to no less than 5
                        nusLength = shortenSubName(nusLength, excess, 5);
                    }
                    StringBuilder sb =
                        new StringBuilder(prefixLength + nusLength + suffixLength);
                    sb.append(prefixLength < prefix.length() ?
                        prefix.substring(0, prefixLength) : prefix);
                    sb.append(nusLength < nus.length() ?
                        nus.substring(0, nusLength) : nus);
                    sb.append(suffixLength < suffix.length() ?
                        suffix.substring(0, suffixLength) : suffix);
                    name = sb.toString();
                }
                // Normalize the path component
                name = fs.normalize(name);
                File f = new File(dir, name);
                if (!name.equals(f.getName()) || f.isInvalid()) {
                    if (System.getSecurityManager() != null)
                        throw new IOException("Unable to create temporary file");
                    else
                        throw new IOException("Unable to create temporary file, "
                            + name);
                }
                return f;
            }
        }
        public static File createTempFile(String prefix, String suffix,
                                          File directory)
            throws IOException
        {
            if (prefix.length() < 3) {
                throw new IllegalArgumentException("Prefix string \"" + prefix +
                    "\" too short: length must be at least 3");
            }
            if (suffix == null)
                suffix = ".tmp";
            File tmpdir = (directory != null) ? directory
                                              : TempDirectory.location();
            SecurityManager sm = System.getSecurityManager();
            File f;
            do {
                f = TempDirectory.generateFile(prefix, suffix, tmpdir);
                if (sm != null) {
                    try {
                        sm.checkWrite(f.getPath());
                    } catch (SecurityException se) {
                        // don't reveal temporary directory location
                        if (directory == null)
                            throw new SecurityException("Unable to create temporary file");
                        throw se;
                    }
                }
            } while ((fs.getBooleanAttributes(f) & FileSystem.BA_EXISTS) != 0);
            if (!fs.createFileExclusively(f.getPath()))
                throw new IOException("Unable to create temporary file");
            return f;
        }
        public static File createTempFile(String prefix, String suffix)
            throws IOException
        {
            return createTempFile(prefix, suffix, null);
        }
        /* — Basic infrastructure — */
        public int compareTo(File pathname) {
            return fs.compare(this, pathname);
        }
        public boolean equals(Object obj) {
            if ((obj != null) && (obj instanceof File)) {
                return compareTo((File)obj) == 0;
            }
            return false;
        }
        public int hashCode() {
            return fs.hashCode(this);
        }
        public String toString() {
            return getPath();
        }
        private synchronized void writeObject(java.io.ObjectOutputStream s)
            throws IOException
        {
            s.defaultWriteObject();
            s.writeChar(separatorChar); // Add the separator character
        }
        private synchronized void readObject(java.io.ObjectInputStream s)
             throws IOException, ClassNotFoundException
        {
            ObjectInputStream.GetField fields = s.readFields();
            String pathField = (String)fields.get("path", null);
            char sep = s.readChar(); // read the previous separator char
            if (sep != separatorChar)
                pathField = pathField.replace(sep, separatorChar);
            String path = fs.normalize(pathField);
            UNSAFE.putReference(this, PATH_OFFSET, path);
            UNSAFE.putIntVolatile(this, PREFIX_LENGTH_OFFSET, fs.prefixLength(path));
        }
        private static final jdk.internal.misc.Unsafe UNSAFE
                = jdk.internal.misc.Unsafe.getUnsafe();
        private static final long PATH_OFFSET
                = UNSAFE.objectFieldOffset(File.class, "path");
        private static final long PREFIX_LENGTH_OFFSET
                = UNSAFE.objectFieldOffset(File.class, "prefixLength");
        private static final long serialVersionUID = 301077366599181567L;
        // — Integration with java.nio.file —
        private transient volatile Path filePath;
        public Path toPath() {
            Path result = filePath;
            if (result == null) {
                synchronized (this) {
                    result = filePath;
                    if (result == null) {
                        result = FileSystems.getDefault().getPath(path);
                        filePath = result;
                    }
                }
            }
            return result;
        }
    }