#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(); работает нормально и никаких других проблем в коде. Главное, что я хочу реализовать, — это логика, о которой я упоминал выше