FileInputStream.java revision d45b1db47a0258ecb532671e87ebd5ec3df28498
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard;
210f524004b71b732c888d10eab57008bc65d8a3e0Owen Lin
22ae704b984c10a63883cc366e823d53902d6ac7a9Elliott Hughesimport java.nio.NioUtils;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.FileChannel;
24a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays;
25dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesimport libcore.io.ErrnoException;
260b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge;
2799a89dd6f0a0e1396aa9b3feebf15ea31f703d3aElliott Hughesimport libcore.io.IoUtils;
28dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesimport libcore.io.Libcore;
29ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams;
30dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesimport static libcore.io.OsConstants.*;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
33024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * An input stream that reads bytes from a file.
34024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <pre>   {@code
35024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *   File file = ...
36024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *   InputStream in = null;
37024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *   try {
38024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *     in = new BufferedInputStream(new FileInputStream(file));
39024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *     ...
40024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *   } finally {
41024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *     if (in != null) {
42024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *       in.close();
43024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *     }
44024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *   }
45024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * }</pre>
46024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *
47024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <p>This stream is <strong>not buffered</strong>. Most callers should wrap
48024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * this stream with a {@link BufferedInputStream}.
49024784c977a744708ab0bcefc4337d491e429937Jesse Wilson *
50024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <p>Use {@link FileReader} to read characters, as opposed to bytes, from a
51024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * file.
52f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson *
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see BufferedInputStream
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see FileOutputStream
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
56d45b1db47a0258ecb532671e87ebd5ec3df28498Elliott Hughespublic class FileInputStream extends InputStream {
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
58b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes    private FileDescriptor fd;
59b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes    private final boolean shouldClose;
60462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes
61024784c977a744708ab0bcefc4337d491e429937Jesse Wilson    /** The unique file channel. Lazily initialized because it's rarely needed. */
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private FileChannel channel;
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom    private final CloseGuard guard = CloseGuard.get();
65f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
67024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * Constructs a new {@code FileInputStream} that reads from {@code file}.
68f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param file
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the file from which this stream reads.
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws FileNotFoundException
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code file} does not exist.
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public FileInputStream(File file) throws FileNotFoundException {
755839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson        if (file == null) {
76a008cf079f1cb812ec42a4fcc941fe170cc9b40dElliott Hughes            throw new NullPointerException("file == null");
775839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson        }
780b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        this.fd = IoBridge.open(file.getAbsolutePath(), O_RDONLY);
79b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes        this.shouldClose = true;
8012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom        guard.open("close");
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
84024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * Constructs a new {@code FileInputStream} that reads from {@code fd}.
85f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param fd
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            the FileDescriptor from which this stream reads.
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws NullPointerException
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if {@code fd} is {@code null}.
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public FileInputStream(FileDescriptor fd) {
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (fd == null) {
93a008cf079f1cb812ec42a4fcc941fe170cc9b40dElliott Hughes            throw new NullPointerException("fd == null");
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.fd = fd;
96b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes        this.shouldClose = false;
97bd3f08d95b31543b5f1fe3d93594efc9c8a2879bBrian Carlstrom        // Note that we do not call guard.open here because the
98bd3f08d95b31543b5f1fe3d93594efc9c8a2879bBrian Carlstrom        // FileDescriptor is not owned by the stream.
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
102024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * Equivalent to {@code new FileInputStream(new File(path))}.
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
104024784c977a744708ab0bcefc4337d491e429937Jesse Wilson    public FileInputStream(String path) throws FileNotFoundException {
105024784c977a744708ab0bcefc4337d491e429937Jesse Wilson        this(new File(path));
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int available() throws IOException {
1100b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        return IoBridge.available(fd);
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
115f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        guard.close();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
117024784c977a744708ab0bcefc4337d491e429937Jesse Wilson            if (channel != null) {
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                channel.close();
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
120b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes            if (shouldClose) {
121b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes                IoUtils.close(fd);
122b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes            } else {
123b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes                // An owned fd has been invalidated by IoUtils.close, but
124b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes                // we need to explicitly stop using an unowned fd (http://b/4361076).
125b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes                fd = new FileDescriptor();
126b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes            }
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Ensures that all resources for this stream are released when it is about
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to be garbage collected.
133f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson     *
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             if an error occurs attempting to finalize this stream.
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
137e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom    @Override protected void finalize() throws IOException {
138024784c977a744708ab0bcefc4337d491e429937Jesse Wilson        try {
13912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom            if (guard != null) {
14012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom                guard.warnIfOpen();
14112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom            }
142e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            close();
143e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        } finally {
144e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            try {
145e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom                super.finalize();
146e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            } catch (Throwable t) {
14763fcdd7e833df417cfbd60961a5167ce637f3071Brian Carlstrom                // for consistency with the RI, we must override Object.finalize() to
14863fcdd7e833df417cfbd60961a5167ce637f3071Brian Carlstrom                // remove the 'throws Throwable' clause.
149e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom                throw new AssertionError(t);
150e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            }
151024784c977a744708ab0bcefc4337d491e429937Jesse Wilson        }
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
155024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * Returns a read-only {@link FileChannel} that shares its position with
156024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * this stream.
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public FileChannel getChannel() {
159024784c977a744708ab0bcefc4337d491e429937Jesse Wilson        synchronized (this) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (channel == null) {
16152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes                channel = NioUtils.newFileChannel(this, fd, O_RDONLY);
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return channel;
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
168024784c977a744708ab0bcefc4337d491e429937Jesse Wilson     * Returns the underlying file descriptor.
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public final FileDescriptor getFD() throws IOException {
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return fd;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
174ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes    @Override public int read() throws IOException {
175ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes        return Streams.readSingleByte(this);
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17826c7025a7a919044771fb89031161bd26fe03032Elliott Hughes    @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
1790b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes        return IoBridge.read(fd, buffer, byteOffset, byteCount);
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
183024784c977a744708ab0bcefc4337d491e429937Jesse Wilson    public long skip(long byteCount) throws IOException {
184024784c977a744708ab0bcefc4337d491e429937Jesse Wilson        if (byteCount < 0) {
185a1603838fe9e865575c87982e32c6343740e464cElliott Hughes            throw new IOException("byteCount < 0: " + byteCount);
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1870f524004b71b732c888d10eab57008bc65d8a3e0Owen Lin        try {
188dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            // Try lseek(2). That returns the new offset, but we'll throw an
189dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            // exception if it couldn't perform exactly the seek we asked for.
190dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            Libcore.os.lseek(fd, byteCount, SEEK_CUR);
191dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            return byteCount;
192dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes        } catch (ErrnoException errnoException) {
193dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            if (errnoException.errno == ESPIPE) {
194dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes                // You can't seek on a pipe, so fall back to the superclass' implementation.
195dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes                return super.skip(byteCount);
1960f524004b71b732c888d10eab57008bc65d8a3e0Owen Lin            }
197dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes            throw errnoException.rethrowAsIOException();
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
201