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