FileUtils.java revision 053f61d6a6e23825e680dc49982e55c5b4299d61
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.os;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkeyimport android.util.Log;
20d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
2190619816d99154d504a14774c6f2d5f4254ff780Guang Zhuimport java.io.BufferedInputStream;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.ByteArrayOutputStream;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileInputStream;
256d25a990afffd5eb385aba3043d5dfad36f1539aWink Savilleimport java.io.FileNotFoundException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileOutputStream;
27da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwoodimport java.io.FileWriter;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.InputStream;
30d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkeyimport java.util.Arrays;
31d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkeyimport java.util.Comparator;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern;
336d25a990afffd5eb385aba3043d5dfad36f1539aWink Savilleimport java.util.zip.CRC32;
346d25a990afffd5eb385aba3043d5dfad36f1539aWink Savilleimport java.util.zip.CheckedInputStream;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Tools for managing files.  Not for public consumption.
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
406d25a990afffd5eb385aba3043d5dfad36f1539aWink Savillepublic class FileUtils {
41d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey    private static final String TAG = "FileUtils";
42d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IRWXU = 00700;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IRUSR = 00400;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IWUSR = 00200;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IXUSR = 00100;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IRWXG = 00070;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IRGRP = 00040;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IWGRP = 00020;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IXGRP = 00010;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IRWXO = 00007;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IROTH = 00004;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IWOTH = 00002;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int S_IXOTH = 00001;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Regular expression for safe filenames: no spaces or metacharacters */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native int setPermissions(String file, int mode, int uid, int gid);
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
63053f61d6a6e23825e680dc49982e55c5b4299d61Dianne Hackborn    public static native int getUid(String file);
64053f61d6a6e23825e680dc49982e55c5b4299d61Dianne Hackborn
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** returns the FAT file system volume ID for the volume mounted
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * at the given mount point, or -1 for failure
676d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     * @param mountPoint point for FAT volume
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return volume ID or -1
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static native int getFatVolumeId(String mountPoint);
718bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn
728bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn    /**
738bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn     * Perform an fsync on the given FileOutputStream.  The stream at this
748bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn     * point must be flushed but not yet closed.
758bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn     */
768bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn    public static boolean sync(FileOutputStream stream) {
778bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn        try {
788bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn            if (stream != null) {
798bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                stream.getFD().sync();
808bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn            }
818bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn            return true;
828bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn        } catch (IOException e) {
838bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn        }
848bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn        return false;
858bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn    }
868bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // copy a file from srcFile to destFile, return true if succeed, return
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // false if fail
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean copyFile(File srcFile, File destFile) {
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = false;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            InputStream in = new FileInputStream(srcFile);
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                result = copyToFile(in, destFile);
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally  {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                in.close();
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result = false;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10390619816d99154d504a14774c6f2d5f4254ff780Guang Zhu
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Copy data from a source stream to destFile.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return true if succeed, return false if failed.
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean copyToFile(InputStream inputStream, File destFile) {
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1101afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn            if (destFile.exists()) {
1111afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn                destFile.delete();
1121afd1c90ebe789b8d3a137004127a50d2db7e3b5Dianne Hackborn            }
1138bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn            FileOutputStream out = new FileOutputStream(destFile);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] buffer = new byte[4096];
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int bytesRead;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while ((bytesRead = inputStream.read(buffer)) >= 0) {
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    out.write(buffer, 0, bytesRead);
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
1218bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                out.flush();
1228bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                try {
1238bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                    out.getFD().sync();
1248bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                } catch (IOException e) {
1258bdf5935c0db4a66ab33a10b43398d2523cfa15dDianne Hackborn                }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                out.close();
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (IOException e) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Check if a filename is "safe" (no metacharacters or spaces).
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param file  The file to check
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static boolean isFilenameSafe(File file) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Note, we check whether it matches what's known to be safe,
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // rather than what's known to be unsafe.  Non-ASCII, control
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // characters, etc. are all unsafe by default.
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return SAFE_FILENAME_PATTERN.matcher(file.getPath()).matches();
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Read a text file into a String, optionally limiting the length.
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param file to read (will not seek, so things like /proc files are OK)
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param max length (positive for head, negative of tail, 0 for no limit)
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param ellipsis to add of the file was truncated (can be null)
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the contents of the file, possibly truncated
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IOException if something goes wrong reading the file
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static String readTextFile(File file, int max, String ellipsis) throws IOException {
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputStream input = new FileInputStream(file);
15590619816d99154d504a14774c6f2d5f4254ff780Guang Zhu        // wrapping a BufferedInputStream around it because when reading /proc with unbuffered
15690619816d99154d504a14774c6f2d5f4254ff780Guang Zhu        // input stream, bytes read not equal to buffer size is not necessarily the correct
15790619816d99154d504a14774c6f2d5f4254ff780Guang Zhu        // indication for EOF; but it is true for BufferedInputStream due to its implementation.
15890619816d99154d504a14774c6f2d5f4254ff780Guang Zhu        BufferedInputStream bis = new BufferedInputStream(input);
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
16042471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor            long size = file.length();
16142471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor            if (max > 0 || (size > 0 && max == 0)) {  // "head" mode: read the first N bytes
16242471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor                if (size > 0 && (max == 0 || size < max)) max = (int) size;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] data = new byte[max + 1];
16490619816d99154d504a14774c6f2d5f4254ff780Guang Zhu                int length = bis.read(data);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length <= 0) return "";
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (length <= max) return new String(data, 0, length);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ellipsis == null) return new String(data, 0, max);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return new String(data, 0, max) + ellipsis;
16942471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor            } else if (max < 0) {  // "tail" mode: keep the last N
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int len;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean rolled = false;
172d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey                byte[] last = null;
173d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey                byte[] data = null;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (last != null) rolled = true;
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    byte[] tmp = last; last = data; data = tmp;
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (data == null) data = new byte[-max];
17890619816d99154d504a14774c6f2d5f4254ff780Guang Zhu                    len = bis.read(data);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (len == data.length);
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (last == null && len <= 0) return "";
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (last == null) return new String(data, 0, len);
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (len > 0) {
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    rolled = true;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.arraycopy(last, len, last, 0, last.length - len);
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.arraycopy(data, 0, last, last.length - len, len);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ellipsis == null || !rolled) return new String(last);
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ellipsis + new String(last);
19042471dd5552a346dd82a58a663159875ccc4fb79Dan Egnor            } else {  // "cat" mode: size unknown, read it all in streaming fashion
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ByteArrayOutputStream contents = new ByteArrayOutputStream();
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int len;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                byte[] data = new byte[1024];
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
19590619816d99154d504a14774c6f2d5f4254ff780Guang Zhu                    len = bis.read(data);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (len > 0) contents.write(data, 0, len);
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (len == data.length);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return contents.toString();
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20190619816d99154d504a14774c6f2d5f4254ff780Guang Zhu            bis.close();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            input.close();
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
205da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood
206da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood   /**
207da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     * Writes string to file. Basically same as "echo -n $string > $filename"
208da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     *
209da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     * @param filename
210da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     * @param string
211da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     * @throws IOException
212da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood     */
213da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood    public static void stringToFile(String filename, String string) throws IOException {
214da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood        FileWriter out = new FileWriter(filename);
215da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood        try {
216da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood            out.write(string);
217da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood        } finally {
218da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood            out.close();
219da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood        }
220da8bb74b9d9ffcb095815db800d0816c411f1fbaMike Lockwood    }
2211b9a6a6e58fd73b5d1b6a434d17f0a69806858ecWink Saville
2226d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville    /**
2236d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     * Computes the checksum of a file using the CRC32 checksum routine.
2246d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     * The value of the checksum is returned.
2256d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     *
2266d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     * @param file  the file to checksum, must not be null
2276d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     * @return the checksum value or an exception is thrown.
2286d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville     */
2296d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville    public static long checksumCrc32(File file) throws FileNotFoundException, IOException {
2306d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville        CRC32 checkSummer = new CRC32();
2316d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville        CheckedInputStream cis = null;
2326d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville
2336d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville        try {
2346d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            cis = new CheckedInputStream( new FileInputStream(file), checkSummer);
2356d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            byte[] buf = new byte[128];
2366d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            while(cis.read(buf) >= 0) {
2376d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville                // Just read for checksum to get calculated.
2386d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            }
2396d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            return checkSummer.getValue();
2406d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville        } finally {
2416d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            if (cis != null) {
2426d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville                try {
2436d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville                    cis.close();
2446d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville                } catch (IOException e) {
2456d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville                }
2466d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville            }
2476d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville        }
2486d25a990afffd5eb385aba3043d5dfad36f1539aWink Saville    }
249d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
250d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey    /**
251d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     * Delete older files in a directory until only those matching the given
252d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     * constraints remain.
253d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     *
254d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     * @param minCount Always keep at least this many files.
255d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     * @param minAge Always keep files younger than this age.
256d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey     */
257d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey    public static void deleteOlderFiles(File dir, int minCount, long minAge) {
258d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        if (minCount < 0 || minAge < 0) {
259d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            throw new IllegalArgumentException("Constraints must be positive or 0");
260d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        }
261d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
262d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        final File[] files = dir.listFiles();
263d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        if (files == null) return;
264d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
265d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        // Sort with newest files first
266d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        Arrays.sort(files, new Comparator<File>() {
267d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            @Override
268d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            public int compare(File lhs, File rhs) {
269d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey                return (int) (rhs.lastModified() - lhs.lastModified());
270d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            }
271d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        });
272d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
273d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        // Keep at least minCount files
274d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        for (int i = minCount; i < files.length; i++) {
275d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            final File file = files[i];
276d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey
277d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            // Keep files newer than minAge
278d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            final long age = System.currentTimeMillis() - file.lastModified();
279d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            if (age > minAge) {
280d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey                Log.d(TAG, "Deleting old file " + file);
281d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey                file.delete();
282d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey            }
283d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey        }
284d9526907d1a51ef0b35bfbbeee43fa209d8b5bbfJeff Sharkey    }
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
286