1/* 2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { BusinessError } from '@ohos.base'; 17import fs from '@ohos.file.fs'; 18import { bufferToString, expect, Logger, sleep } from '../../common/Common'; 19 20const CONTENT = 'hello world'; 21const TAG: string = '[FileIO].[Watcher]'; 22const TIMEOUT: number = 500; // 超时时间 23const IN_ACCESS: number = 0x00000001; 24const IN_MODIFY: number = 0x00000002; 25const IN_ATTRIB: number = 0x00000004; 26const IN_CLOSE_WRITE: number = 0x00000008; 27const IN_CLOSE_NOWRITE: number = 0x00000010; 28const IN_OPEN: number = 0x00000020; 29const IN_MOVED_FROM: number = 0x00000040; 30const IN_MOVED_TO: number = 0x00000080; 31const IN_CREATE: number = 0x00000100; 32const IN_DELETE: number = 0x00000200; 33const IN_DELETE_SELF: number = 0x00000400; 34const IN_MOVE_SELF: number = 0x00000800; 35const IN_ISDIR: number = 0x40000000; 36const BUFFER: number = 4096; // 读写文件buffer大小 37const FILE_NUMBER: number = 9; // 文件1-9命名时加上0 38 39interface FILEINFO { 40 path: string[], 41 size: number 42} 43export default class MyWatcher { 44 public fileSize: number = 0; 45 private baseDir: string = ''; 46 public watcherList: Array<fs.Watcher> = []; 47 private timeOut: number = TIMEOUT; 48 public log: string[] = []; 49 public fileInfo: FILEINFO= { 50 path: [], 51 size: 0 52 }; 53 private watcherCodeMap = new Map([ 54 ['IN_ACCESS', IN_ACCESS], 55 ['IN_MODIFY', IN_MODIFY], 56 ['IN_ATTRIB', IN_ATTRIB], 57 ['IN_CLOSE_WRITE', IN_CLOSE_WRITE], 58 ['IN_CLOSE_NOWRITE', IN_CLOSE_NOWRITE], 59 ['IN_OPEN', IN_OPEN], 60 ['IN_MOVED_FROM', IN_MOVED_FROM], 61 ['IN_MOVED_TO', IN_MOVED_TO], 62 ['IN_CREATE', IN_CREATE], 63 ['IN_DELETE', IN_DELETE], 64 ['IN_DELETE_SELF', IN_DELETE_SELF], 65 ['IN_MOVE_SELF', IN_MOVE_SELF], 66 ['IN_ISDIR', IN_ISDIR] 67 ]); 68 public content1: string = AppStorage.get<string>('fileContent1') as string; 69 public content2: string = AppStorage.get<string>('fileContent2') as string; 70 public content3: string = AppStorage.get<string>('fileContent3') as string; 71 public content4: string = AppStorage.get<string>('fileContent4') as string; 72 73 constructor() { 74 this.baseDir = AppStorage.get<string>('sanBoxFileDir') as string; 75 } 76 77 startWatcher(watcherName: string): void { 78 let watcherDir: string = this.baseDir + '/watcherDir'; 79 Logger.info(TAG, `${watcherName}-startWatcher start path = ${watcherDir}`); 80 if (this.watcherCodeMap.has(watcherName)) { // 是否存在key 'watchName': true 81 try { 82 Logger.info(TAG, `${watcherName}-startWatcher has watchName`); 83 let watcher: fs.Watcher = fs.createWatcher(watcherDir, this.watcherCodeMap.get(watcherName), (data) => { //获取key对应的value 84 if (data.event === IN_ACCESS) { 85 Logger.info('startWatcher ' + data.fileName + ' was accessed'); 86 } else if (data.event === IN_MODIFY) { 87 Logger.info('startWatcher ' + data.fileName + ' was modified'); 88 } else if (data.event === IN_ATTRIB) { 89 Logger.info('startWatcher ' + data.fileName + ' was attributed'); 90 } else if (data.event === IN_CLOSE_WRITE) { 91 Logger.info('startWatcher ' + data.fileName + ' was in close write'); 92 } else if (data.event === IN_CLOSE_NOWRITE) { 93 Logger.info('startWatcher ' + data.fileName + ' was closed'); 94 } else if (data.event === IN_OPEN) { 95 Logger.info('startWatcher ' + data.fileName + ' was opened'); 96 } else if (data.event === IN_MOVED_FROM) { 97 Logger.info('startWatcher ' + data.fileName + ' was moved to other path'); 98 } else if (data.event === IN_MOVED_TO) { 99 Logger.info('startWatcher ' + data.fileName + ' was moved in this path'); 100 } else if (data.event === IN_CREATE) { 101 Logger.info('startWatcher ' + data.fileName + ' was added'); 102 } else if (data.event === IN_DELETE) { 103 Logger.info('startWatcher ' + data.fileName + ' was deleted '); 104 } else if (data.event === IN_DELETE_SELF) { 105 Logger.info('startWatcher ' + data.fileName + ' was deleted and stop watcher'); 106 } else if (data.event === IN_MOVE_SELF) { 107 Logger.info('startWatcher ' + data.fileName + ' was moved and continue watcher'); 108 } else if (data.event === IN_ISDIR) { 109 Logger.info('startWatcher ' + data.fileName + ' was watch all event'); 110 } else { 111 Logger.info('startWatcher fail'); 112 } 113 AppStorage.setOrCreate('eventLog', JSON.stringify(data.event)); 114 AppStorage.setOrCreate('fileNameLog', data.fileName); 115 AppStorage.setOrCreate('cookieLog', JSON.stringify(data.cookie)); 116 Logger.info(TAG, `${watcherName}-startWatcher :{event: ${data.event}, fileName: ${data.fileName}, cookie: ${data.cookie}}`); 117 }); 118 119 watcher.start(); 120 setTimeout(async () => { 121 this.watcherList.push(watcher); 122 }, this.timeOut); 123 124 Logger.info('watcherList is ' + JSON.stringify(this.watcherList)); 125 } catch (e) { 126 Logger.error(TAG, `${watcherName}-startWatcher has failed for: {message: ${e.message}, code: ${e.code}}`); 127 } 128 } else { 129 Logger.info(TAG, `${watcherName}-startWatcher does not in watcherCodeMap`); 130 } 131 } 132 133 stopWatcher(watcher: fs.Watcher, index: number): void { 134 if (watcher !== null) { 135 watcher.stop(); 136 setTimeout(async () => { 137 this.watcherList.splice(index, 1); 138 }, this.timeOut); 139 Logger.info(TAG, 'stopWatcher successful'); 140 } else { 141 Logger.info(TAG, 'stopWatcher null'); 142 } 143 } 144 145 readyFilesToWatcher(pathDir: string): void { 146 let content = this.content1 + '\r\n' + this.content2 + '\r\n' + this.content3 + '\r\n' + this.content4; 147 148 try { 149 let flag = TAG; 150 if (!fs.accessSync(pathDir)) { 151 fs.mkdirSync(pathDir); 152 } 153 let dpath = pathDir; 154 Logger.info('readyFileToWatcher dpath = ' + dpath); 155 for (let i = 0; i < FILE_NUMBER; i++) { 156 let myFile = dpath + `/TestFile0${i + 1}.txt`; 157 Logger.info('readyFileToWatcher myFile = ' + myFile); 158 let file = fs.openSync(myFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE | fs.OpenMode.TRUNC); 159 fs.writeSync(file.fd, content); 160 fs.closeSync(file); 161 } 162 Logger.info(TAG, 'readyFileToWatcher successful'); 163 } catch (e) { 164 Logger.error(TAG, `readyFileToWatcher has failed for: {message: ${e.message}, code: ${e.code}}`); 165 } 166 } 167 168 addFileToWatcher(path: string): void { 169 let content = CONTENT + '\n'; 170 try { 171 let addFile = this.baseDir + '/watcherDir/' + path; 172 Logger.info('addFileToWatcher addFile = ' + addFile); 173 let file = fs.openSync(addFile, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE | fs.OpenMode.TRUNC); 174 fs.writeSync(file.fd, content); 175 fs.closeSync(file); 176 } catch (e) { 177 Logger.error(TAG, `addFileToWatcher has failed for: {message: ${e.message}, code: ${e.code}}`); 178 } 179 } 180 181 deleteFileToWatcher(path: string): void { 182 try { 183 let deleteFile = this.baseDir + '/watcherDir/' + path; 184 Logger.info(TAG, 'deleteFileToWatcher deleteFile = ' + deleteFile); 185 fs.unlink(deleteFile).then(() => { 186 Logger.info(TAG, 'deleteFileToWatcher file succeed'); 187 }).catch((err: BusinessError) => { 188 Logger.info(TAG, 'deleteFileToWatcher file failed with error message: ' + err.message + ', error code: ' + err.code); 189 }); 190 } catch (e) { 191 Logger.error(TAG, `readyFileToWatcher has failed for: {message: ${e.message}, code: ${e.code}}`); 192 } 193 } 194 195 modifyFileNameToWatcher(oldName: string, newName: string): boolean { 196 try { 197 let srcFile = this.baseDir + '/watcherDir/' + oldName; 198 Logger.info(TAG, 'modifyFileNameToWatcher srcFile = ' + srcFile); 199 let dstFile = this.baseDir + '/watcherDir/' + newName; 200 Logger.info(TAG, 'modifyFileNameToWatcher dstFile = ' + dstFile); 201 fs.renameSync(srcFile, dstFile); 202 return true; 203 } catch (e) { 204 Logger.info(`-readyFileRW-creat has failed for: {message: ${e.message}, code: ${e.code}}`); 205 return false; 206 } 207 } 208 209 modifyFileContentToWatcher(fileName: string, content: string): boolean { 210 let filePath = this.baseDir + '/watcherDir/' + fileName; 211 Logger.info(TAG, 'modifyFileContentToWatcher filePath = ' + filePath); 212 try { 213 let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC); 214 let writeLen = fs.writeSync(file.fd, content); 215 Logger.info(TAG, 'modifyFileContentToWatcher write data to file succeed and size is:' + writeLen); 216 fs.closeSync(file); 217 let fileRead = fs.openSync(filePath, fs.OpenMode.READ_WRITE); 218 let buf = new ArrayBuffer(BUFFER); 219 this.fileSize = fs.readSync(fileRead.fd, buf); 220 let resultPut = bufferToString(buf); 221 Logger.info('modifyFileContentToWatcher Read num = ' + this.fileSize); 222 Logger.info('modifyFileContentToWatcher Read resultPut = ' + resultPut); 223 fs.closeSync(fileRead); 224 Logger.info('modifyFileContentToWatcher write data to file succeed and fileSize is:' + this.fileSize); 225 return true; 226 } catch (e) { 227 Logger.info(`-readyFileRW-creat has failed for: {message: ${e.message}, code: ${e.code}}`); 228 return false; 229 } 230 } 231 232 modifyFileToWatcher(oldName: string, newName: string, content: string): number { 233 // 重命名文件 234 let filePath = ''; 235 if (newName.trim() === oldName.trim()) { 236 filePath = this.baseDir + '/watcherDir/' + oldName; 237 Logger.info('modifyFileToWatcher The new file name is the same as the old file name'); 238 } else { 239 try { 240 let srcFile = this.baseDir + '/watcherDir/' + oldName; 241 Logger.info('modifyFileToWatcher srcFile = ' + srcFile); 242 let dstFile = this.baseDir + '/watcherDir/' + newName; 243 filePath = dstFile; 244 Logger.info('modifyFileToWatcher dstFile = ' + dstFile); 245 fs.renameSync(srcFile, dstFile); 246 } catch (e) { 247 Logger.info(`modifyFileToWatcher -readyFileRW-creat has failed for: {message: ${e.message}, code: ${e.code}}`); 248 } 249 } 250 251 // 修改文件内容 252 Logger.info('modifyFileContentToWatcher filePath = ' + filePath); 253 try { 254 let file = fs.openSync(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC); 255 let writeLen = fs.writeSync(file.fd, content); 256 Logger.info('modifyFileContentToWatcher write data to file succeed and size is:' + writeLen); 257 fs.closeSync(file); 258 259 let fileRead = fs.openSync(filePath, fs.OpenMode.READ_WRITE); 260 let buf = new ArrayBuffer(BUFFER); 261 this.fileSize = fs.readSync(fileRead.fd, buf); 262 let resultPut = bufferToString(buf); 263 Logger.info('modifyFileContentToWatcher Read num = ' + this.fileSize); 264 Logger.info('modifyFileContentToWatcher Read resultPut = ' + resultPut); 265 fs.closeSync(fileRead); 266 Logger.info('modifyFileContentToWatcher write data to file succeed and fileSize is:' + this.fileSize); 267 } catch (e) { 268 Logger.info(`-readyFileRW-creat has failed for: {message: ${e.message}, code: ${e.code}}`); 269 } 270 return this.fileSize; 271 } 272}