Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.io;
     18 
     19 import java.io.File;
     20 import java.io.FileDescriptor;
     21 import java.io.IOException;
     22 import java.io.RandomAccessFile;
     23 import java.net.Socket;
     24 import java.nio.charset.Charsets;
     25 import static libcore.io.OsConstants.*;
     26 
     27 public final class IoUtils {
     28     private IoUtils() {
     29     }
     30 
     31     /**
     32      * Calls close(2) on 'fd'. Also resets the internal int to -1. Does nothing if 'fd' is null
     33      * or invalid.
     34      */
     35     public static void close(FileDescriptor fd) throws IOException {
     36         try {
     37             if (fd != null && fd.valid()) {
     38                 Libcore.os.close(fd);
     39             }
     40         } catch (ErrnoException errnoException) {
     41             throw errnoException.rethrowAsIOException();
     42         }
     43     }
     44 
     45     /**
     46      * Closes 'closeable', ignoring any checked exceptions. Does nothing if 'closeable' is null.
     47      */
     48     public static void closeQuietly(AutoCloseable closeable) {
     49         if (closeable != null) {
     50             try {
     51                 closeable.close();
     52             } catch (RuntimeException rethrown) {
     53                 throw rethrown;
     54             } catch (Exception ignored) {
     55             }
     56         }
     57     }
     58 
     59     /**
     60      * Closes 'fd', ignoring any exceptions. Does nothing if 'fd' is null or invalid.
     61      */
     62     public static void closeQuietly(FileDescriptor fd) {
     63         try {
     64             IoUtils.close(fd);
     65         } catch (IOException ignored) {
     66         }
     67     }
     68 
     69     /**
     70      * Closes 'socket', ignoring any exceptions. Does nothing if 'socket' is null.
     71      */
     72     public static void closeQuietly(Socket socket) {
     73         if (socket != null) {
     74             try {
     75                 socket.close();
     76             } catch (Exception ignored) {
     77             }
     78         }
     79     }
     80 
     81     /**
     82      * Sets 'fd' to be blocking or non-blocking, according to the state of 'blocking'.
     83      */
     84     public static void setBlocking(FileDescriptor fd, boolean blocking) throws IOException {
     85         try {
     86             int flags = Libcore.os.fcntlVoid(fd, F_GETFL);
     87             if (!blocking) {
     88                 flags |= O_NONBLOCK;
     89             } else {
     90                 flags &= ~O_NONBLOCK;
     91             }
     92             Libcore.os.fcntlLong(fd, F_SETFL, flags);
     93         } catch (ErrnoException errnoException) {
     94             throw errnoException.rethrowAsIOException();
     95         }
     96     }
     97 
     98     /**
     99      * Returns the contents of 'path' as a byte array.
    100      */
    101     public static byte[] readFileAsByteArray(String path) throws IOException {
    102         return readFileAsBytes(path).toByteArray();
    103     }
    104 
    105     /**
    106      * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
    107      */
    108     public static String readFileAsString(String path) throws IOException {
    109         return readFileAsBytes(path).toString(Charsets.UTF_8);
    110     }
    111 
    112     private static UnsafeByteSequence readFileAsBytes(String path) throws IOException {
    113         RandomAccessFile f = null;
    114         try {
    115             f = new RandomAccessFile(path, "r");
    116             UnsafeByteSequence bytes = new UnsafeByteSequence((int) f.length());
    117             byte[] buffer = new byte[8192];
    118             while (true) {
    119                 int byteCount = f.read(buffer);
    120                 if (byteCount == -1) {
    121                     return bytes;
    122                 }
    123                 bytes.write(buffer, 0, byteCount);
    124             }
    125         } finally {
    126             IoUtils.closeQuietly(f);
    127         }
    128     }
    129 
    130     /**
    131      * Recursively delete everything in {@code dir}.
    132      */
    133     // TODO: this should specify paths as Strings rather than as Files
    134     public static void deleteContents(File dir) throws IOException {
    135         File[] files = dir.listFiles();
    136         if (files == null) {
    137             throw new IllegalArgumentException("not a directory: " + dir);
    138         }
    139         for (File file : files) {
    140             if (file.isDirectory()) {
    141                 deleteContents(file);
    142             }
    143             if (!file.delete()) {
    144                 throw new IOException("failed to delete file: " + file);
    145             }
    146         }
    147     }
    148 }
    149