Добавление логики (метода) управления размером файла для управления размером log.txt файл, который мы храним во внутренней памяти устройства

#java #android #android-studio #file-handling #logcat

#java #Android #android-studio #обработка файлов #logcat

Вопрос:

У нас есть система управления журналами, которая распечатывает в файле logcat во время работы приложения. Каждый день появляется новый файл, а файл журнала за предыдущий день удаляется. Проблема в том, что если пользователь использует приложение в течение длительного периода времени, файл журнала становится довольно большим по размеру и может достигать GBs.

Нам нужна система управления журналами, которая позволяет избежать этого, чтобы всегда иметь обновленные журналы разумного размера, в идеале менее 150-200 Мб. Файл журнала — простой текстовый файл, в котором сохраняется logcat. С того момента, как каждая строка в этом файле соответствует определенному времени, я подумал, что когда файл достигает 150 Мб, первые x строк удаляются, чтобы уменьшить размер файла, сохраняя последние журналы, важные, которые нам нужны, чтобы хранить только файл за день. Нам не нужны вчерашние файлы

Логика может быть:

 if today 20201128 delete 20201127
   create a directory with the datum "20201128"
   create file 20201128_11_52 in it
 

создайте систему управления

 while file < 200 mb do nothing
then
open new file logs in it
close old file
zip old file
if 20201128 > 2 GB sent mail to us,
somethis is going worong
 

Ниже приведен текущий код, с которым мы работаем

     public class startLogging {
​
    static String globalLogName = "logcat-"   getCurrentDate()   "-.txt";
​
    public static void startLog(){
​
        if (isExternalStorageWritable()) {
            //Delete old logs
            deleteOldLogs();
​
            File logDirectory      = new File(Environment.getExternalStorageDirectory().getPath()  "/ElenaLogs/");
            File logFile           = new File(logDirectory, globalLogName );
​
​
            // create log folder
            if (!logDirectory.exists()) {
                logDirectory.mkdir();
            }
​
            // clear the previous logcat and then write the new one to the file
            try {
                Process process     = Runtime.getRuntime().exec("logcat -c");
                process             = Runtime.getRuntime().exec("logcat -f "   logFile);
            } catch ( IOException e ) {
                e.printStackTrace();
            }
​
        }
    }
​
    private static boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }
​
    private static String getCurrentDate(){
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
        Date date = new Date();
        //Return the date in this format: 20200515, that is a larger number every day, more easy to delete old logs
        return formatter.format(date).replace("/", "");
    }
​
    public static String getCurrentLogPath(){
        return Environment.getExternalStorageDirectory().getPath()  "/ElenaLogs/"   globalLogName;
    }
​
    private static String[] getFilesInDir(){
        //Get all the files in the ElenaLogs dir
        String[] fileNames;
        File f = new File(Environment.getExternalStorageDirectory().getPath() "/ElenaLogs");
        fileNames = f.list();
        return fileNames;
    }
​
    private static boolean deleteFile(String dateToDelete){
​
        String globalPath           = Environment.getExternalStorageDirectory().getPath()  "/ElenaLogs/";
​
        String fileToDelete         = "logcat-" dateToDelete "-.txt";
        String pathFile             = globalPath   fileToDelete;
​
        String zipToDelete          = "logcat-" dateToDelete "-.zip";
        String pathZip             = globalPath   zipToDelete;
​
        File filetoDelete               = new File(pathFile);
        File ziptoDelete                = new File(pathZip);
​
        ziptoDelete.delete();
​
        return filetoDelete.delete();
    }
​
    private static void deleteOldLogs(){
​
        String          date                    = getCurrentDate();
        int             dateNumber              = Integer.parseInt(date);
        String[]        allLogs                 = getFilesInDir();
​
        try{
            for (String logFileName : allLogs) {
​
                int logDate = Integer.parseInt(logFileName.split("-")[1]);
​
                if (logDate < dateNumber) {
                    //Old file, delete
                    deleteFile(String.valueOf(logDate));
                }
​
            }
        }catch (NullPointerException e){
            e.printStackTrace();
        }
​
​
    }
​
    public static String getPathForEmail(){
​
        String zippedFilename   =   globalLogName.replace(".txt", ".zip");
        String zippedFilePath   =   Environment.getExternalStorageDirectory().getPath()   "/ElenaLogs/"   zippedFilename;
​
        //Zip the current log file
        if (zipFileAtPath(getCurrentLogPath(), zippedFilePath)){
            return zippedFilePath;
        }else {
            return getCurrentLogPath();
        }
​
    }
​
    /** Zips the logs**/public static boolean zipFileAtPath(String sourcePath, String toLocation) {
        final int BUFFER = 2048;
​
        File sourceFile = new File(sourcePath);
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(toLocation);
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
                    dest));
            if (sourceFile.isDirectory()) {
                zipSubFolder(out, sourceFile, sourceFile.getParent().length());
            } else {
                byte data[] = new byte[BUFFER];
                FileInputStream fi = new FileInputStream(sourcePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
                entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
            }
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
​
​
    private static void zipSubFolder(ZipOutputStream out, File folder,
                              int basePathLength) throws IOException {
​
        final int BUFFER = 2048;
​
        File[] fileList = folder.listFiles();
        BufferedInputStream origin = null;
        for (File file : fileList) {
            if (file.isDirectory()) {
                zipSubFolder(out, file, basePathLength);
            } else {
                byte data[] = new byte[BUFFER];
                String unmodifiedFilePath = file.getPath();
                String relativePath = unmodifiedFilePath
                        .substring(basePathLength);
                FileInputStream fi = new FileInputStream(unmodifiedFilePath);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(relativePath);
                entry.setTime(file.lastModified()); // to keep modification time after unzipping
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
            }
        }
    }
​
    /*
     * gets the last path component
     *
     * Example: getLastPathComponent("downloads/example/fileToZip");
     * Result: "fileToZip"
     */
    private static String getLastPathComponent(String filePath) {
        String[] segments = filePath.split("/");
        if (segments.length == 0)
            return "";
        String lastPathComponent = segments[segments.length - 1];
        return lastPathComponent;
    }
​
}
 

Я попытался реализовать приведенную ниже логику после долгих поисков в самом первом методе, т.е. startlog() в приведенном выше коде. Но это не работает.

 if(logFile.length()/1024*1024>150){
    Log.d(globalLogName,"greaterFileSize" logFile.length());
    process=Runtime.getRuntime().exec("tail -n  500" logFile.getName());
}
 

Реализована приведенная выше логика в startlog(), как показано ниже-

 public static void startLog() {
        if (isExternalStorageWritable()) {
            //Delete old logs
            deleteOldLogs();
            File logDirectory = new File(Environment.getExternalStorageDirectory().getPath()   "/ElenaLogs/");
            File logFile = new File(logDirectory, globalLogName);
            // create log folder
            if (!logDirectory.exists()) {
                logDirectory.mkdir();
            }
            // clear the previous logcat and then write the new one to the file
            try {
                Log.d(globalLogName,"greaterFileSize" logFile.length());
                Process process = Runtime.getRuntime().exec("logcat -c");
                process = Runtime.getRuntime().exec("logcat -f "   logFile);
                if(logFile.length()/1024*1024>150){
                    Log.d(globalLogName,"greaterFileSize" logFile.length());
                    process=Runtime.getRuntime().exec("tail -n  500" logFile.getName());
                }
            } catch (IOException e) {
                Log.d(globalLogName,"greaterFileSize" logFile.length());
                e.printStackTrace();
            }
        }
    }
 

Комментарии:

1. Мне не хватает кода, в котором часть вашего приложения хочет что-то зарегистрировать и вызывает ваш регистратор для добавления строки. Пожалуйста, покажите.

2. logDirectory.mkdir(); Проверьте возвращаемое значение, поскольку оно может не создать каталог. Обработайте соответствующим образом.

3. isExternalStorageWritable() Это не проверяет возможность записи. Нет устройства Android 10?

4. @blackapps logDirectory.mkdir(); работает нормально и никаких других проблем в коде. Главное, что я хочу реализовать, — это логика, о которой я упоминал выше