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