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 225d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport android.system.ErrnoException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.nio.channels.FileChannel; 245d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport java.nio.NioUtils; 250b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughesimport libcore.io.IoBridge; 26dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesimport libcore.io.Libcore; 27ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughesimport libcore.io.Streams; 285d930cadc8f62aee5f18e7921296fe66a54f18abElliott Hughesimport static android.system.OsConstants.*; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 31024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * An input stream that reads bytes from a file. 32024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <pre> {@code 33024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * File file = ... 34024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * InputStream in = null; 35024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * try { 36024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * in = new BufferedInputStream(new FileInputStream(file)); 37024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * ... 38024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * } finally { 39024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * if (in != null) { 40024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * in.close(); 41024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * } 42024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * } 43024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * }</pre> 44024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * 45024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <p>This stream is <strong>not buffered</strong>. Most callers should wrap 46024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * this stream with a {@link BufferedInputStream}. 47024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * 48024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * <p>Use {@link FileReader} to read characters, as opposed to bytes, from a 49024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * file. 50f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see BufferedInputStream 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see FileOutputStream 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 54d45b1db47a0258ecb532671e87ebd5ec3df28498Elliott Hughespublic class FileInputStream extends InputStream { 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 56b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes private FileDescriptor fd; 57b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes private final boolean shouldClose; 58462bdac45c10f43d88d8f07f6994e272a27c14a2Elliott Hughes 59024784c977a744708ab0bcefc4337d491e429937Jesse Wilson /** The unique file channel. Lazily initialized because it's rarely needed. */ 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private FileChannel channel; 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 63f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 65024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * Constructs a new {@code FileInputStream} that reads from {@code file}. 66f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param file 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the file from which this stream reads. 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws FileNotFoundException 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code file} does not exist. 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public FileInputStream(File file) throws FileNotFoundException { 735839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson if (file == null) { 74a008cf079f1cb812ec42a4fcc941fe170cc9b40dElliott Hughes throw new NullPointerException("file == null"); 755839b909d9528b7726e678a4b696ed37df15d897Jesse Wilson } 765fecee2da855e92afbcba3a231f4685a56f17967Narayan Kamath this.fd = IoBridge.open(file.getPath(), O_RDONLY); 77b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes this.shouldClose = true; 7812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.open("close"); 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 82024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * Constructs a new {@code FileInputStream} that reads from {@code fd}. 83f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param fd 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the FileDescriptor from which this stream reads. 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code fd} is {@code null}. 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public FileInputStream(FileDescriptor fd) { 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (fd == null) { 91a008cf079f1cb812ec42a4fcc941fe170cc9b40dElliott Hughes throw new NullPointerException("fd == null"); 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.fd = fd; 94b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes this.shouldClose = false; 95bd3f08d95b31543b5f1fe3d93594efc9c8a2879bBrian Carlstrom // Note that we do not call guard.open here because the 96bd3f08d95b31543b5f1fe3d93594efc9c8a2879bBrian Carlstrom // FileDescriptor is not owned by the stream. 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 100024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * Equivalent to {@code new FileInputStream(new File(path))}. 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 102024784c977a744708ab0bcefc4337d491e429937Jesse Wilson public FileInputStream(String path) throws FileNotFoundException { 103024784c977a744708ab0bcefc4337d491e429937Jesse Wilson this(new File(path)); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int available() throws IOException { 1080b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.available(fd); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 113f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 115024784c977a744708ab0bcefc4337d491e429937Jesse Wilson if (channel != null) { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project channel.close(); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes if (shouldClose) { 119f0d40d662d9dfdb04215c718961765837d2cf00cNeil Fuller IoBridge.closeAndSignalBlockedThreads(fd); 120b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes } else { 121b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes // An owned fd has been invalidated by IoUtils.close, but 122b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes // we need to explicitly stop using an unowned fd (http://b/4361076). 123b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes fd = new FileDescriptor(); 124b1f55cb6f95928be969a8fe5c7447e13f14d0a68Elliott Hughes } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Ensures that all resources for this stream are released when it is about 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to be garbage collected. 131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs attempting to finalize this stream. 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 135e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws IOException { 136024784c977a744708ab0bcefc4337d491e429937Jesse Wilson try { 13712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 13812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 13912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 140e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom close(); 141e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 142e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 143e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 144e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } catch (Throwable t) { 14563fcdd7e833df417cfbd60961a5167ce637f3071Brian Carlstrom // for consistency with the RI, we must override Object.finalize() to 14663fcdd7e833df417cfbd60961a5167ce637f3071Brian Carlstrom // remove the 'throws Throwable' clause. 147e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom throw new AssertionError(t); 148e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 149024784c977a744708ab0bcefc4337d491e429937Jesse Wilson } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 153024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * Returns a read-only {@link FileChannel} that shares its position with 154024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * this stream. 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public FileChannel getChannel() { 157024784c977a744708ab0bcefc4337d491e429937Jesse Wilson synchronized (this) { 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (channel == null) { 15952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes channel = NioUtils.newFileChannel(this, fd, O_RDONLY); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return channel; 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 166024784c977a744708ab0bcefc4337d491e429937Jesse Wilson * Returns the underlying file descriptor. 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public final FileDescriptor getFD() throws IOException { 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return fd; 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 172ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes @Override public int read() throws IOException { 173ff8234c90ecab9f1db368924bf92a5b16460f9b5Elliott Hughes return Streams.readSingleByte(this); 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17626c7025a7a919044771fb89031161bd26fe03032Elliott Hughes @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException { 1770b736ebc4efef64f2db1999aea90297ad8196146Elliott Hughes return IoBridge.read(fd, buffer, byteOffset, byteCount); 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 181024784c977a744708ab0bcefc4337d491e429937Jesse Wilson public long skip(long byteCount) throws IOException { 182024784c977a744708ab0bcefc4337d491e429937Jesse Wilson if (byteCount < 0) { 183a1603838fe9e865575c87982e32c6343740e464cElliott Hughes throw new IOException("byteCount < 0: " + byteCount); 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1850f524004b71b732c888d10eab57008bc65d8a3e0Owen Lin try { 186dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes // Try lseek(2). That returns the new offset, but we'll throw an 187dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes // exception if it couldn't perform exactly the seek we asked for. 188dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes Libcore.os.lseek(fd, byteCount, SEEK_CUR); 189dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes return byteCount; 190dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes } catch (ErrnoException errnoException) { 191dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes if (errnoException.errno == ESPIPE) { 192dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes // You can't seek on a pipe, so fall back to the superclass' implementation. 193dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes return super.skip(byteCount); 1940f524004b71b732c888d10eab57008bc65d8a3e0Owen Lin } 195dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes throw errnoException.rethrowAsIOException(); 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 199