From d600a5fb23baaf1c57fa8f0a0b62a9eddd12101b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=85=B4=E4=BA=91?= <1459475768@qq.com> Date: Thu, 13 Apr 2023 01:09:52 +0800 Subject: [PATCH] =?UTF-8?q?=E9=82=B9=E5=85=B4=E4=BA=91=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/micode/notes/tool/BackupUtils.java | 97 +++++++++++++------ 1 file changed, 70 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/net/micode/notes/tool/BackupUtils.java b/app/src/main/java/net/micode/notes/tool/BackupUtils.java index 39f6ec4..8dbec2e 100644 --- a/app/src/main/java/net/micode/notes/tool/BackupUtils.java +++ b/app/src/main/java/net/micode/notes/tool/BackupUtils.java @@ -47,23 +47,28 @@ public class BackupUtils { } return sInstance; } +/* `TAG` 是一个 String 常量,用于标识日志输出的 tag。 + `sInstance` 是一个静态变量,用于存储单例实例。 + `getInstance()` 是一个静态方法,通过传入一个 `Context` 参数获取 `BackupUtils` 的单例实例。 + 这里使用了双重检查锁定来确保线程安全。 +*/ /** - * Following states are signs to represents backup or restore + * Following states are signs to represents backup or restore(以下是表示备份或恢复的符号) * status */ // Currently, the sdcard is not mounted public static final int STATE_SD_CARD_UNMOUONTED = 0; - // The backup file not exist + // The backup file not exist(备份文件不存在) public static final int STATE_BACKUP_FILE_NOT_EXIST = 1; - // The data is not well formated, may be changed by other programs + // The data is not well formated, may be changed by other programs(数据格式不正确可能被其他程序更改) public static final int STATE_DATA_DESTROIED = 2; - // Some run-time exception which causes restore or backup fails + // Some run-time exception which causes restore or backup fails(导致备份或还原失败的默写运行异常) public static final int STATE_SYSTEM_ERROR = 3; - // Backup or restore success + // Backup or restore success(备份或还原成功) public static final int STATE_SUCCESS = 4; - private TextExport mTextExport; + private TextExport mTextExport;//实例化对象 private BackupUtils(Context context) { mTextExport = new TextExport(context); @@ -75,15 +80,15 @@ public class BackupUtils { public int exportToText() { return mTextExport.exportToText(); - } + }//这是一个 public 方法,用于将数据导出为文本,并返回一个整数值。 public String getExportedTextFileName() { return mTextExport.mFileName; - } + }//这是一个 public 方法,用于获取导出的文本文件名。 public String getExportedTextFileDir() { return mTextExport.mFileDirectory; - } + }//这是一个 public 方法,用于获取导出的文本文件所在的目录。 private static class TextExport { private static final String[] NOTE_PROJECTION = { @@ -91,7 +96,8 @@ public class BackupUtils { NoteColumns.MODIFIED_DATE, NoteColumns.SNIPPET, NoteColumns.TYPE - }; + };//这是一个私有的静态内部类,用于完成数据导出的操作。 + private static final int NOTE_COLUMN_ID = 0; @@ -115,32 +121,37 @@ public class BackupUtils { private static final int DATA_COLUMN_CALL_DATE = 2; private static final int DATA_COLUMN_PHONE_NUMBER = 4; + // 定义了多个常量,用于操作笔记和数据的列索引 private final String [] TEXT_FORMAT; private static final int FORMAT_FOLDER_NAME = 0; private static final int FORMAT_NOTE_DATE = 1; private static final int FORMAT_NOTE_CONTENT = 2; + // 定义了一个字符串数组 TEXT_FORMAT,其中存储了导出笔记时的文件格式 private Context mContext; private String mFileName; private String mFileDirectory; + // 定义了 Context mContext、String mFileName、String mFileDirectory 三个变量 + // mContext 存储了当前上下文,mFileName 存储了文件名,mFileDirectory 存储了文件夹路径 public TextExport(Context context) { TEXT_FORMAT = context.getResources().getStringArray(R.array.format_for_exported_note); mContext = context; mFileName = ""; - mFileDirectory = ""; + mFileDirectory = "";// 构造函数,初始化了 TEXT_FORMAT、mContext、mFileName 和 mFileDirectory } private String getFormat(int id) { return TEXT_FORMAT[id]; - } + }// getFormat 方法返回 TEXT_FORMAT 数组中指定 id 的字符串 /** * Export the folder identified by folder id to text + * (exportFolderToText 方法用于将指定文件夹下的笔记导出到文本中) */ private void exportFolderToText(String folderId, PrintStream ps) { - // Query notes belong to this folder + // Query notes belong to this folder// 查询属于该文件夹的笔记 Cursor notesCursor = mContext.getContentResolver().query(Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, NoteColumns.PARENT_ID + "=?", new String[] { folderId @@ -149,11 +160,11 @@ public class BackupUtils { if (notesCursor != null) { if (notesCursor.moveToFirst()) { do { - // Print note's last modified date + // Print note's last modified date // 输出笔记的最后修改日期 ps.println(String.format(getFormat(FORMAT_NOTE_DATE), DateFormat.format( mContext.getString(R.string.format_datetime_mdhm), notesCursor.getLong(NOTE_COLUMN_MODIFIED_DATE)))); - // Query data belong to this note + // Query data belong to this note // 查询属于该笔记的数据 String noteId = notesCursor.getString(NOTE_COLUMN_ID); exportNoteToText(noteId, ps); } while (notesCursor.moveToNext()); @@ -169,14 +180,14 @@ public class BackupUtils { Cursor dataCursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION, DataColumns.NOTE_ID + "=?", new String[] { noteId - }, null); + }, null);// exportNoteToText 方法用于将指定笔记的数据导出到文本中 if (dataCursor != null) { if (dataCursor.moveToFirst()) { do { String mimeType = dataCursor.getString(DATA_COLUMN_MIME_TYPE); if (DataConstants.CALL_NOTE.equals(mimeType)) { - // Print phone number + // Print phone number // 输出电话号码 String phoneNumber = dataCursor.getString(DATA_COLUMN_PHONE_NUMBER); long callDate = dataCursor.getLong(DATA_COLUMN_CALL_DATE); String location = dataCursor.getString(DATA_COLUMN_CONTENT); @@ -185,11 +196,11 @@ public class BackupUtils { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), phoneNumber)); } - // Print call date + // Print call date// 输出通话日期 ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), DateFormat .format(mContext.getString(R.string.format_datetime_mdhm), callDate))); - // Print call attachment location + // Print call attachment location // 输出通话附件位置 if (!TextUtils.isEmpty(location)) { ps.println(String.format(getFormat(FORMAT_NOTE_CONTENT), location)); @@ -205,7 +216,7 @@ public class BackupUtils { } dataCursor.close(); } - // print a line separator between note + // print a line separator between note// 在导出每个笔记后输出一个分隔符 try { ps.write(new byte[] { Character.LINE_SEPARATOR, Character.LETTER_NUMBER @@ -222,14 +233,20 @@ public class BackupUtils { if (!externalStorageAvailable()) { Log.d(TAG, "Media was not mounted"); return STATE_SD_CARD_UNMOUONTED; - } + }/*这段代码的作用是向指定的PrintStream对象中写入一个分隔符。它使用了Java中的byte数组,其中包含了两个特殊的字符:Character.LINE_SEPARATOR和Character.LETTER_NUMBER。 + + Character.LINE_SEPARATOR表示平台的行分隔符,其值因平台而异。例如,在Windows中,它的值是"\r\n",在Unix/Linux中,它的值是"\n"。 + + Character.LETTER_NUMBER是一个没有实际意义的字符,它只是被用来作为分隔符的一部分。 + + 当这个byte数组被写入PrintStream对象时,它会在文本中插入一个分隔符,以便在文本中区分不同的笔记。如果写入过程中发生IOException,那么会在Logcat中输出相应的错误信息。*/ PrintStream ps = getExportToTextPrintStream(); if (ps == null) { Log.e(TAG, "get print stream error"); return STATE_SYSTEM_ERROR; - } - // First export folder and its notes + }//这段代码中的 getExportToTextPrintStream() 是一个自定义方法,它返回一个 PrintStream 对象,该对象用于将笔记数据导出到文本文件中 + // First export folder and its notes//“首先导出文件夹及其包含的笔记” Cursor folderCursor = mContext.getContentResolver().query( Notes.CONTENT_NOTE_URI, NOTE_PROJECTION, @@ -255,7 +272,11 @@ public class BackupUtils { } while (folderCursor.moveToNext()); } folderCursor.close(); - } + }/*这段代码的作用是导出所有文件夹及其包含的笔记。 + + 首先,通过调用 ContentResolver 的 query() 方法查询所有的文件夹和 Call Record 文件夹,同时排除回收站中的笔记,将结果保存在 Cursor 对象 folderCursor 中。 + + 接着,通过遍历 folderCursor 中的所有记录,获取每个文件夹的名称和ID,并将其写入到输出流 ps 中。如果当前文件夹是 Call Record 文件夹,则使用字符串资源文件中的值作为文件夹的名称*/ // Export notes in root's folder Cursor noteCursor = mContext.getContentResolver().query( @@ -280,7 +301,13 @@ public class BackupUtils { ps.close(); return STATE_SUCCESS; - } + }/*这段代码的作用是导出根文件夹中的所有笔记。 + + 首先,通过调用 ContentResolver 的 query() 方法查询根文件夹中的所有笔记,并将结果保存在 Cursor 对象 noteCursor 中。 + + 接着,通过遍历 noteCursor 中的所有记录,获取每个笔记的修改日期,并将其写入到输出流 ps 中。然后,调用 exportNoteToText() 方法,将当前笔记的内容导出到输出流 ps 中。 + + 最后,关闭输出流 ps,并返回 STATE_SUCCESS 表示导出笔记数据成功。如果 noteCursor 为空,则不会做任何处理,直接关闭输出流并返回成功状态。*/ /** * Get a print stream pointed to the file {@generateExportedTextFile} @@ -307,7 +334,15 @@ public class BackupUtils { } return ps; } - } + }/*这段代码的作用是创建一个输出流 PrintStream 对象,用于将笔记数据导出到文本文件中。 + +首先,通过调用 generateFileMountedOnSDcard() 方法获取导出文件的路径和名称,并将结果保存在 File 对象 file 中。 + +接着,检查 file 是否为 null。如果是,则在Logcat中输出 "create file to exported failed" 的错误信息,并返回 null。 + +然后,获取 file 的名称和路径,并创建一个 FileOutputStream 对象 fos,将其作为参数传递给 PrintStream 构造函数,创建一个 PrintStream 对象 ps。 + +最后,返回 ps 对象,如果在创建 PrintStream 对象时出现 FileNotFoundException 或 NullPointerException 异常,则返回 null*/ /** * Generate the text file to store imported data @@ -339,6 +374,14 @@ public class BackupUtils { return null; } -} +}/*这段代码的作用是生成一个文件对象,并返回该对象的引用。 + +首先,获取外部存储设备的根目录,并将其与 filePathResId 参数所指定的路径拼接成一个完整的路径,并将其保存在 StringBuilder 对象 sb 中。 + +接着,创建一个 File 对象 filedir,用于表示存储导出文件的目录。如果该目录不存在,则调用 mkdir() 方法创建该目录。 + +然后,使用 fileNameFormatResId 参数所指定的文件名格式,将当前日期和时间添加到 sb 中,形成完整的文件路径。最后,创建一个 File 对象 file,用于表示导出的文件。 + +最后,检查 file 和 filedir 是否存在。如果它们都存在,则直接返回 file 对象的引用。否则,通过捕捉 SecurityException 和 IOException 异常,输出异常信息,并返回 null。*/