├── 1452822_洪嘉勇_文件系统 ├── fileSystem2.jar ├── 1452822_洪嘉勇_文件系统项目文档.pdf ├── myFiles.java ├── tableModel.java ├── Block.java └── UI.java └── README.md /1452822_洪嘉勇_文件系统/fileSystem2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hjyheart/Project-for-os-fileSystem/HEAD/1452822_洪嘉勇_文件系统/fileSystem2.jar -------------------------------------------------------------------------------- /1452822_洪嘉勇_文件系统/1452822_洪嘉勇_文件系统项目文档.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Hjyheart/Project-for-os-fileSystem/HEAD/1452822_洪嘉勇_文件系统/1452822_洪嘉勇_文件系统项目文档.pdf -------------------------------------------------------------------------------- /1452822_洪嘉勇_文件系统/myFiles.java: -------------------------------------------------------------------------------- 1 | package fileSystem2; 2 | 3 | import java.io.File; 4 | 5 | /** 6 | * Created by hongjiayong on 16/6/7. 7 | */ 8 | public class myFiles { 9 | private int blockName; 10 | private File myFile; 11 | private String fileName; 12 | double space; 13 | 14 | public myFiles(File myFile, int blockName, double capacity){ 15 | space = capacity; 16 | this.myFile = myFile; 17 | this.blockName = blockName; 18 | fileName = myFile.getName(); 19 | } 20 | 21 | public String getFileName(){ 22 | return myFile.getName(); 23 | } 24 | 25 | public String getFilePath(){ 26 | return myFile.toString(); 27 | } 28 | 29 | public boolean renameFile(String name){ 30 | String c = myFile.getParent(); 31 | File mm = new File(c + File.separator + name); 32 | if (myFile.renameTo(mm)){ 33 | myFile = mm; 34 | fileName = name; 35 | return true; 36 | }else{ 37 | return false; 38 | } 39 | } 40 | 41 | public File getMyFile(){ 42 | return myFile; 43 | } 44 | 45 | public int getBlockName() { 46 | return blockName; 47 | } 48 | 49 | public double getSpace() { 50 | return space; 51 | } 52 | 53 | @Override 54 | public String toString(){ 55 | return fileName; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /1452822_洪嘉勇_文件系统/tableModel.java: -------------------------------------------------------------------------------- 1 | package fileSystem2; 2 | 3 | import javax.swing.table.AbstractTableModel; 4 | import java.text.DecimalFormat; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Date; 7 | import java.util.Vector; 8 | 9 | /** 10 | * Created by hongjiayong on 16/6/7. 11 | */ 12 | public class tableModel extends AbstractTableModel { 13 | private Vector content = null; 14 | private String[] title_name = { "File Name", "File Path", "File Type", "File Volume/KB", "Last Update"}; 15 | 16 | public tableModel(){ 17 | content = new Vector(); 18 | } 19 | 20 | public void addRow(myFiles myFile){ 21 | Vector v = new Vector(); 22 | DecimalFormat format=new DecimalFormat("#0.00"); 23 | v.add(0, myFile.getFileName()); 24 | v.add(1, myFile.getFilePath()); 25 | if (myFile.getMyFile().isFile()){ 26 | v.add(2, "File"); 27 | v.add(3, format.format(myFile.getSpace())); 28 | }else { 29 | v.add(2, "Directory"); 30 | v.add(3, "-"); 31 | } 32 | long time = myFile.getMyFile().lastModified(); 33 | String ctime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(time)); 34 | v.add(4, ctime); 35 | content.add(v); 36 | } 37 | 38 | public void removeRow(String name) { 39 | for (int i = 0; i < content.size(); i++){ 40 | if (((Vector)content.get(i)).get(0).equals(name)){ 41 | content.remove(i); 42 | break; 43 | } 44 | } 45 | } 46 | 47 | public void removeRows(int row, int count){ 48 | for (int i = 0; i < count; i++){ 49 | if (content.size() > row){ 50 | content.remove(row); 51 | } 52 | } 53 | } 54 | 55 | @Override 56 | public void setValueAt(Object value, int rowIndex, int colIndex){ 57 | ((Vector) content.get(rowIndex)).remove(colIndex); 58 | ((Vector) content.get(rowIndex)).add(colIndex, value); 59 | this.fireTableCellUpdated(rowIndex, colIndex); 60 | } 61 | 62 | public String getColumnName(int col) { 63 | return title_name[col]; 64 | } 65 | 66 | @Override 67 | public boolean isCellEditable(int rowIndex, int columnIndex){ 68 | return false; 69 | } 70 | 71 | @Override 72 | public int getRowCount() { 73 | return content.size(); 74 | } 75 | 76 | @Override 77 | public int getColumnCount() { 78 | return title_name.length; 79 | } 80 | 81 | @Override 82 | public Object getValueAt(int rowIndex, int columnIndex) { 83 | return ((Vector) content.get(rowIndex)).get(columnIndex); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 文件系统大作业说明文档 2 | ## ID: 3 | ## Name: 4 |
5 | ## 目录 6 | 7 | 8 | 9 | - [项目需求](#项目需求) 10 | - [具体技术细节](#具体技术细节) 11 | - [开发工具](#开发工具) 12 | - [文件系统管理方案](#文件系统管理方案) 13 | - [存储空间概述](#存储空间概述) 14 | - [存储空间管理方式](#存储空间管理方式) 15 | - [空闲空间管理方式](#空闲空间管理方式) 16 | - [文件目录结构](#文件目录结构) 17 | - [FCB](#fcb) 18 | - [概述](#概述) 19 | - [内容](#内容) 20 | - [程序操作指南](#程序操作指南) 21 | - [特殊文件说明](#特殊文件说明) 22 | - [BitMap&&Fat.txt](#bitmapfattxt) 23 | - [recover.txt](#recovertxt) 24 | - [程序概述](#程序概述) 25 | - [界面构成](#界面构成) 26 | - [搜索框](#搜索框) 27 | - [算法](#算法) 28 | - [文件树](#文件树) 29 | - [显示框](#显示框) 30 | - [底部盘信息栏](#底部盘信息栏) 31 | - [菜单项](#菜单项) 32 | - [注意事项](#注意事项) 33 | - [文件系统实现功能](#文件系统实现功能) 34 | - [文件目录](#文件目录) 35 | - [创建文件](#创建文件) 36 | - [概述](#概述-1) 37 | - [实现方法](#实现方法) 38 | - [删除文件](#删除文件) 39 | - [概述](#概述-2) 40 | - [实现方法](#实现方法-1) 41 | - [重命名(更改当前目录)](#重命名(更改当前目录)) 42 | - [概述](#概述-3) 43 | - [实现方法](#实现方法-2) 44 | - [打开文件](#打开文件) 45 | - [关闭文件](#关闭文件) 46 | - [写文件](#写文件) 47 | - [读文件](#读文件) 48 | - [格式化](#格式化) 49 | - [概述](#概述-4) 50 | - [实现方法](#实现方法-3) 51 | - [数据结构](#数据结构) 52 | - [盘区(Block)](#盘区(block)) 53 | 54 | 55 | ## 项目需求 56 | 在内存中开辟一个空间作为文件存储器,在其上实现一个简单的文件系统。 57 | 退出这个文件系统时,需要该文件系统的内容保存到磁盘上,以便下次可 58 | 以将其恢复到内存中来。 59 | ## 具体技术细节 60 | - 文件存储空间管理可采取显式链接(如FAT)或者其他方法。(即自选一种方法) 61 | - 空闲空间管理可采用位图或者其他方法。如果采用了位图,可将位图和FAT表合二为一。 62 | - 文件目录采用多级目录结构。至于是否采用索引节点结构,自选。目录项目中应包含:文件名、物理地址、长度等信息。同学可在这里增加一些其他信息。 63 | ## 开发工具 64 | 环境: intellij 65 | 语言: Java 66 | ## 文件系统管理方案 67 | ### 存储空间概述 68 | 盘区数量:10 69 | 盘区大小:1024KB 70 | ### 存储空间管理方式 71 | FAT:在本次项目中,我的文件系统管理方案采用了显式链接的方式,在每 72 | 一个盘区都开了一个文件用来存储当前盘区所有存储块的使用情况。并记 73 | 录盘区内所有文件所占用内存块的情况 74 | 75 | 优点:不存在内外内存碎片,最大程度地利用了盘区空间。 76 | ### 空闲空间管理方式 77 | 位图:在本次项目中,我的文件系统空闲空间管理方案采用了位图。使用一串 78 | 0和1来标识内存块的状态。0为未使用,1表示已经被占用。创建文件时从最前方 79 | 开始检索空闲块,确定使用后将0置为1。 80 | 81 | 优点:一目了然,易于管理。 82 | ### 文件目录结构 83 | 多级目录结构 84 | ### FCB 85 | #### 概述 86 | 该文件系统的FCB将直接显示在生成的txt文本中,以文本头的形势呈现。 87 | 需要编辑内容可以将内容写在FCB下方的划分线内。 88 | #### 内容 89 | - 大小 90 | - 文件名 91 | - 地址 92 | - 最近更新时间 93 | 94 | ## 程序操作指南 95 | ### 特殊文件说明 96 | #### BitMap&&Fat.txt 97 | 该文件存储了盘区的存储块的状态,用0表示还未分配,1表示已经分配 98 | 该文件存储了盘区内存在的文件按照链接方式实现的的内存分配情况,列出了对应内存块的位置 99 | #### recover.txt 100 | 该文件是当前盘区的备份文档,在再次启动该应用程序的时候通过读取该文件的信息还原出上次的 101 | 运行状态,从而实现复盘 102 | ### 程序概述 103 | #### 界面构成 104 | - 搜索框 105 | - 文件树 106 | - 显示框 107 | - 底部盘信息栏 108 | ##### 搜索框 109 | 搜索框位于顶部可以在搜索栏中键入文件名或者文件夹名然后点击“start”来进行检索,如果检索成功将直接打开,失败则弹框提醒 110 | ###### 算法 111 | 采用dfs深度搜索的方式 112 | ``` java 113 | // Search a file 114 | public boolean searchFile(String fileName, File parent){ 115 | File [] files = parent.listFiles(); 116 | for (File myFile:files){ 117 | if (myFile.getName().equals(fileName)){ 118 | try { 119 | if(Desktop.isDesktopSupported()) { 120 | Desktop desktop = Desktop.getDesktop(); 121 | desktop.open(myFile); 122 | return true; 123 | } 124 | } catch (IOException e1) { 125 | JOptionPane.showMessageDialog(null, myFile.getPath() + " Sorry, some thing wrong!", "Fail to open", 126 | JOptionPane.ERROR_MESSAGE); 127 | return true; 128 | } 129 | } 130 | if (myFile.isDirectory() && myFile.canRead()){ 131 | if(searchFile(fileName, myFile)){ 132 | return true; 133 | } 134 | } 135 | } 136 | return false; 137 | } 138 | 139 | ``` 140 | ##### 文件树 141 | 文件树位于左侧,呈现文件的目录结构,详情见目录结构 142 | ##### 显示框 143 | 显示框位于程序右侧,用于显示文件的名称、路径、类型、大小和最近修改时间 144 | ##### 底部盘信息栏 145 | 底部盘信息栏位于程序的底部,用于显示当前选中盘区的名称、已使用空间、未使用空间、文件数量 146 | #### 菜单项 147 | - create a file(生成一个文件) 148 | - create a dir(生成一个文件夹) 149 | - delete(删除一个文件或文件夹) 150 | - format(格式化) 151 | - rename(重命名) 152 | 153 | ### 注意事项 154 | - 必须先选择一个系统内的文件夹作为模拟工作目录 155 | - 文件操作需要先选中一个文件树中的节点右键才能进行操作 156 | - 本程序重在模拟,并不是真正地为文件开了这么大的空间 157 | - 仅支持生成txt文件,在输入文件名时不需要输入.txt 158 | - 相同目录下已经存在该文件重命名将失败 159 | - 文本中将自动生成FCB,不支持用户去修改FCB 160 | - 非法输入都将导致文件生成失败 161 | - 如果存档文件recover.txt被破坏,将无法在再次打开该程序时恢复盘区信息 162 | 163 | ## 文件系统实现功能 164 | ### 文件目录 165 | 文件目录将呈现在程序的左侧,以十个以数字命名的盘为基目录。 166 | 点击文件夹左侧箭头可以将文件夹展开 167 | **当执行创建和删除文件等操作,必须重新展开一次父目录才能刷新**

168 | ### 创建文件 169 | #### 概述 170 | 选中某一文件后,右键展开功能选项,选择第一项生成文件或第二项就会弹出对话框 171 | 要求键入文件名和文件大小。文件生成成功之后只要重新展开父目录就可以看到新生 172 | 的文件。双击程序右侧的显示区的文件就可以打开该文件看到它的FCB 173 | #### 实现方法 174 | 通过调用File类的createFile()方法来实现 175 | 文件创建成功之后将刷新FAT和位图 176 | 如果存储空间不足或是输入非法将导致文件生成失败 177 | 178 | ``` java 179 | // create a file 180 | public boolean createFile(String filePath){ 181 | boolean result = false; 182 | File file = new File(filePath); 183 | if(!file.exists()){ 184 | try { 185 | result = file.createNewFile(); 186 | } catch (IOException e) { 187 | e.printStackTrace(); 188 | } 189 | } 190 | 191 | return result; 192 | } 193 | ``` 194 | **当执行创建文件操作,必须重新展开一次父目录才能刷新**

195 | 196 | ### 删除文件 197 | #### 概述 198 | 选中某一文件后,右键展开功能选项,选择第三项删除即可删除所选项 199 | #### 实现方法 200 | 通过调用File类的delete()删除 针对文件夹需要递归删除 201 | 文件删除成功之后将刷新FAT和位图 202 | 203 | ``` java 204 | // delete a file 205 | public boolean deleteFile(String filePath){ 206 | boolean result = false; 207 | File file = new File(filePath); 208 | if(file.exists() && file.isFile()){ 209 | result = file.delete(); 210 | } 211 | 212 | return result; 213 | } 214 | ``` 215 | 216 | **当执行删除文件操作,必须重新展开一次父目录才能刷新**

217 | 218 | ### 重命名(更改当前目录) 219 | #### 概述 220 | 选中某一文件后,右键展开功能选项,选择第四项重命名即可对文件或文件夹进行重命名 221 | #### 实现方法 222 | 通过调用File类的renameTo()方法进行重命名 223 | 如果相同目录下有相同的文件,则重命名将失败 224 | **当执行重命名文件操作,必须重新展开一次父目录才能刷新**

225 | 226 | ### 打开文件 227 | 双击程序中右侧的显示面板中的文件即可打开对应文件 228 | ### 关闭文件 229 | 打开文件之后点击文件上方的关闭按钮就可以将对应文件关闭 230 | ### 写文件 231 | 打开文件之后在FCB的内容下方输入文本即可 232 | ### 读文件 233 | 双击程序右侧的显示面板中的文件即可打开对应文件进行查看 234 | ### 格式化 235 | #### 概述 236 | 选中某一文件夹之后右键选择第四项格式化就可以将该文件夹格式化 237 | #### 实现方法 238 | 即递归删除该目录下的所有文件并更新FAT和位图 239 | 240 | ## 数据结构 241 | ### 盘区(Block) 242 | ``` java 243 | public class Block { 244 | // 名称 245 | private int blockName; 246 | // 盘区内的文件 247 | private File blockFile; 248 | // 位图存储文件 249 | private File blockBitMap; 250 | // 恢复文件 251 | private File recover; 252 | // 位图存储文件书写器 253 | private FileWriter bitWriter; 254 | // 恢复文件书写器 255 | private FileWriter recoverWriter; 256 | // 文件数量 257 | private int fileNum; 258 | // 盘区已占用空间 259 | private double space; 260 | // 内存块数组 261 | public int [][] bitmap = new int[32][32]; 262 | // 文件和内存块对应表 263 | private Map filesBit = new HashMap(); 264 | // 文件列表 265 | private ArrayList files = new ArrayList(); 266 | 267 | public Block(int name, File file, boolean rec) throws IOException { 268 | // 初始化 269 | } 270 | 271 | public File getBlockFile(){ 272 | return blockFile; 273 | } 274 | 275 | public void putFCB(File file, double capacity) throws IOException { 276 | // 将FCB写入文件 277 | } 278 | 279 | 280 | public void rewriteBitMap() throws IOException { 281 | // 重写位图存储文件 282 | } 283 | 284 | public void rewriteRecoverWriter() throws IOException{ 285 | // 重写恢复文件 286 | } 287 | 288 | public boolean createFile(File file, double capacity) throws IOException { 289 | // 在盘区内创建文件 290 | } 291 | 292 | public boolean deleteFile(File file, double capacity){ 293 | // 在盘区内删除文件 294 | } 295 | 296 | public boolean renameFile(File file, String name, double capacity) throws IOException { 297 | // 重命名盘区内的文件 298 | } 299 | 300 | public int getFileNum() { 301 | return fileNum; 302 | } 303 | 304 | public double getSpace() { 305 | return space; 306 | } 307 | } 308 | 309 | ``` 310 | -------------------------------------------------------------------------------- /1452822_洪嘉勇_文件系统/Block.java: -------------------------------------------------------------------------------- 1 | package fileSystem2; 2 | 3 | import javax.swing.*; 4 | import java.io.*; 5 | import java.text.SimpleDateFormat; 6 | import java.util.ArrayList; 7 | import java.util.Date; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by hongjiayong on 16/6/7. 13 | */ 14 | public class Block { 15 | private int blockName; 16 | private File blockFile; 17 | private File blockBitMap; 18 | private File recover; 19 | private FileWriter bitWriter; 20 | private FileWriter recoverWriter; 21 | private int fileNum; 22 | private double space; 23 | public int [][] bitmap = new int[32][32]; 24 | private Map filesBit = new HashMap(); 25 | private ArrayList files = new ArrayList(); 26 | 27 | public Block(int name, File file, boolean rec) throws IOException { 28 | blockName = name; 29 | blockFile = file; 30 | blockBitMap = new File(blockFile.getPath() + File.separator + blockName + "BitMap&&Fat.txt"); 31 | recover = new File(blockFile.getPath() + File.separator + "recover.txt"); 32 | if (!rec) { 33 | space = 0; 34 | fileNum = 0; 35 | blockFile.mkdir(); 36 | blockBitMap.createNewFile(); 37 | bitWriter = new FileWriter(blockBitMap); 38 | for (int i = 0; i < 32; i++) { 39 | for (int k = 0; k < 32; k++) { 40 | bitmap[i][k] = 0; 41 | bitWriter.write("0"); 42 | } 43 | bitWriter.write("\r\n"); 44 | } 45 | bitWriter.flush(); 46 | 47 | recover.createNewFile(); 48 | recoverWriter = new FileWriter(recover); 49 | recoverWriter.write(String.valueOf(space) + "\r\n"); 50 | recoverWriter.write(String.valueOf(fileNum) + "\r\n"); 51 | for (int i = 0; i < 32; i++) { 52 | for (int k = 0; k < 32; k++) { 53 | if (bitmap[i][k] == 0) { 54 | recoverWriter.write("0\r\n"); 55 | } else { 56 | recoverWriter.write("1\r\n"); 57 | } 58 | } 59 | } 60 | recoverWriter.flush(); 61 | }else{ 62 | try { 63 | BufferedReader reader = new BufferedReader(new FileReader(recover)); 64 | space = Double.parseDouble(reader.readLine()); 65 | fileNum = Integer.parseInt(reader.readLine()); 66 | for (int i = 0; i < 32; i++) { 67 | for (int k = 0; k < 32; k++) { 68 | if (Integer.parseInt(reader.readLine()) == 0) { 69 | bitmap[i][k] = 0; 70 | } else { 71 | bitmap[i][k] = 1; 72 | } 73 | } 74 | } 75 | String temp; 76 | while ((temp = reader.readLine()) != null) { 77 | File myFile = new File(blockFile.getPath() + File.separator + temp); 78 | files.add(myFile); 79 | int[][] tempBit = new int[32][32]; 80 | for (int i = 0; i < 32; i++) { 81 | for (int k = 0; k < 32; k++) { 82 | if (Integer.parseInt(reader.readLine()) == 0) { 83 | tempBit[i][k] = 0; 84 | } else { 85 | tempBit[i][k] = 1; 86 | } 87 | } 88 | } 89 | filesBit.put(myFile.getName(), tempBit); 90 | } 91 | reader.close(); 92 | }catch (Exception e){ 93 | JOptionPane.showMessageDialog(null, "The files aren't compelete. You can choose another place or delete \"myFileSystem\" in this dir and run this again!", 94 | "Error", JOptionPane.ERROR_MESSAGE); 95 | System.exit(0); 96 | } 97 | } 98 | } 99 | 100 | public File getBlockFile(){ 101 | return blockFile; 102 | } 103 | 104 | public void putFCB(File file, double capacity) throws IOException { 105 | FileWriter newFileWriter = new FileWriter(file); 106 | newFileWriter.write("File\r\n"); 107 | newFileWriter.write(String.valueOf(capacity) + "\r\n"); 108 | newFileWriter.write("Name: " + file.getName() + "\r\n"); 109 | newFileWriter.write("Path: " + file.getPath() + "\r\n"); 110 | String ctime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date(file.lastModified())); 111 | newFileWriter.write("Date last updated: " + ctime + "\r\n"); 112 | newFileWriter.write("--------------------------edit file blew ------------------------------\r\n"); 113 | newFileWriter.close(); 114 | } 115 | 116 | 117 | public void rewriteBitMap() throws IOException { 118 | bitWriter = new FileWriter(blockBitMap); 119 | bitWriter.write(""); 120 | for (int i = 0; i < 32;i++){ 121 | for (int k = 0; k < 32; k++){ 122 | if (bitmap[i][k] == 0){ 123 | bitWriter.write("0"); 124 | }else{ 125 | bitWriter.write("1"); 126 | } 127 | } 128 | bitWriter.write("\r\n"); 129 | } 130 | for (int i = 0; i < files.size(); i++){ 131 | bitWriter.write(files.get(i).getName() + ":"); 132 | for (int k = 0; k < 32; k++){ 133 | for (int j = 0; j < 32; j++){ 134 | try { 135 | if (filesBit.get(files.get(i).getName())[k][j] == 1) { 136 | bitWriter.write(String.valueOf(k * 32 + j) + " "); 137 | } 138 | }catch (Exception e){ 139 | System.out.println("wrong"); 140 | } 141 | } 142 | } 143 | bitWriter.write("\r\n"); 144 | } 145 | bitWriter.flush(); 146 | } 147 | 148 | public void rewriteRecoverWriter() throws IOException{ 149 | recoverWriter = new FileWriter(recover); 150 | recoverWriter.write(""); 151 | 152 | recoverWriter.write(String.valueOf(space) + "\r\n"); 153 | recoverWriter.write(String.valueOf(fileNum) + "\r\n"); 154 | for (int i = 0; i < 32; i++){ 155 | for (int k = 0; k < 32; k++){ 156 | if (bitmap[i][k] == 0){ 157 | recoverWriter.write("0\r\n"); 158 | }else{ 159 | recoverWriter.write("1\r\n"); 160 | } 161 | } 162 | } 163 | for (int i = 0; i < files.size(); i++){ 164 | recoverWriter.write(files.get(i).getName() + "\r\n"); 165 | int [][] bitTemp = filesBit.get(files.get(i).getName()); 166 | for (int k = 0; k < 32; k++){ 167 | for (int j = 0; j < 32; j++){ 168 | if (bitTemp[k][j] == 0){ 169 | recoverWriter.write("0\r\n"); 170 | }else { 171 | recoverWriter.write("1\r\n"); 172 | } 173 | } 174 | } 175 | } 176 | recoverWriter.flush(); 177 | } 178 | 179 | public boolean createFile(File file, double capacity) throws IOException { 180 | files.add(file); 181 | file.createNewFile(); 182 | int cap[][] = new int[32][32]; 183 | for (int i = 0; i < 32; i++){ 184 | for (int k = 0; k < 32; k++) 185 | cap[i][k] = 0; 186 | } 187 | BufferedReader in = new BufferedReader(new FileReader(blockBitMap)); 188 | int count = (int) capacity; 189 | for (int i = 0; i < 32; i++){ 190 | String line = in.readLine(); 191 | for (int k = 0; k < 32; k++){ 192 | if (count > 0) { 193 | if (line.charAt(k) == '0') { 194 | count--; 195 | cap[i][k] = 1; 196 | bitmap[i][k] = 1; 197 | } 198 | } 199 | } 200 | } 201 | if (count > 0){ 202 | JOptionPane.showMessageDialog(null, "Insufficient memory!!", "Fail", JOptionPane.ERROR_MESSAGE); 203 | file.delete(); 204 | for (int i = 0; i < 32; i++){ 205 | for (int k = 0; k < 32; k++){ 206 | if (cap[i][k] == 1){ 207 | bitmap[i][k] = 0; 208 | } 209 | } 210 | } 211 | return false; 212 | }else{ 213 | fileNum++; 214 | space += capacity; 215 | filesBit.put(file.getName(), cap); 216 | rewriteBitMap(); 217 | rewriteRecoverWriter(); 218 | // Put FCB 219 | putFCB(file, capacity); 220 | 221 | return true; 222 | } 223 | } 224 | 225 | public boolean deleteFile(File file, double capacity){ 226 | if (file.getName().equals("1") || file.getName().equals("2") || file.getName().equals("3") || file.getName().equals("4") 227 | || file.getName().equals("5") || file.getName().equals("6") || file.getName().equals("7") || file.getName().equals("8") 228 | || file.getName().equals("9") || file.getName().equals("10") || file.getName().equals("1BitMap&&Fat.txt") 229 | || file.getName().equals("2BitMap&&Fat.txt") || file.getName().equals("3BitMap&&Fat.txt") 230 | || file.getName().equals("4BitMap&&Fat.txt") || file.getName().equals("5BitMap&&Fat.txt") 231 | || file.getName().equals("5BitMap&&Fat.txt") || file.getName().equals("6BitMap&&Fat.txt") 232 | || file.getName().equals("7BitMap&&Fat.txt") || file.getName().equals("8BitMap&&Fat.txt") 233 | || file.getName().equals("9BitMap&&Fat.txt") || file.getName().equals("10BitMap&&Fat.txt") 234 | || file.getName().equals("recover.txt")){ 235 | JOptionPane.showMessageDialog(null, "The dir is protected!!", "Access fail", JOptionPane.ERROR_MESSAGE); 236 | return false; 237 | } 238 | 239 | try{ 240 | if (file.isFile()){ 241 | try { 242 | file.delete(); 243 | }catch (Exception e){ 244 | e.printStackTrace(); 245 | } 246 | space -= capacity; 247 | fileNum--; 248 | int[][] fileStore = filesBit.get(file.getName()); 249 | for (int i = 0; i < 32; i++){ 250 | for (int k = 0; k < 32; k++){ 251 | if (bitmap[i][k] == 1 && fileStore[i][k] == 1){ 252 | bitmap[i][k] = 0; 253 | } 254 | } 255 | } 256 | filesBit.remove(file.getName()); 257 | for (int i = 0; i < files.size(); i++){ 258 | if (files.get(i).getName().equals(file.getName())){ 259 | files.remove(i); 260 | break; 261 | } 262 | } 263 | }else{ 264 | File [] files = file.listFiles(); 265 | for(File myFile : files){ 266 | deleteFile(myFile, capacity); 267 | } 268 | while(file.exists()) { 269 | file.delete(); 270 | } 271 | } 272 | return true; 273 | }catch (Exception e){ 274 | System.out.println("fail"); 275 | return false; 276 | } 277 | } 278 | 279 | public boolean renameFile(File file, String name, double capacity) throws IOException { 280 | String oldName = file.getName(); 281 | int[][] tempBit = filesBit.get(oldName); 282 | String c = file.getParent(); 283 | File mm; 284 | if(file.isFile()) { 285 | mm = new File(c + File.separator + name + ".txt"); 286 | if (file.renameTo(mm)){ 287 | file = mm; 288 | filesBit.remove(oldName); 289 | filesBit.put(file.getName(), tempBit); 290 | // Put FCB 291 | putFCB(file, capacity); 292 | for (int i = 0; i < files.size(); i++){ 293 | if (files.get(i).getName().equals(oldName)){ 294 | files.remove(i); 295 | files.add(file); 296 | break; 297 | } 298 | } 299 | rewriteBitMap(); 300 | rewriteRecoverWriter(); 301 | return true; 302 | }else{ 303 | return false; 304 | } 305 | } 306 | else { 307 | mm = new File(c + File.separator + name); 308 | file.renameTo(mm); 309 | return true; 310 | } 311 | } 312 | 313 | public int getFileNum() { 314 | return fileNum; 315 | } 316 | 317 | public double getSpace() { 318 | return space; 319 | } 320 | } 321 | -------------------------------------------------------------------------------- /1452822_洪嘉勇_文件系统/UI.java: -------------------------------------------------------------------------------- 1 | package fileSystem2; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.TreeExpansionEvent; 5 | import javax.swing.event.TreeSelectionEvent; 6 | import javax.swing.event.TreeSelectionListener; 7 | import javax.swing.event.TreeWillExpandListener; 8 | import javax.swing.tree.*; 9 | import java.awt.*; 10 | import java.awt.event.ActionEvent; 11 | import java.awt.event.ActionListener; 12 | import java.awt.event.MouseAdapter; 13 | import java.awt.event.MouseEvent; 14 | import java.io.*; 15 | import java.util.ArrayList; 16 | 17 | /** 18 | * Created by hongjiayong on 16/6/7. 19 | */ 20 | public class UI extends JFrame { 21 | private JTree tree; 22 | private JScrollPane treePane; 23 | private JScrollPane tablePane; 24 | private tableModel model = new tableModel(); 25 | private JTable fileTable; 26 | private JPopupMenu myMenu = new JPopupMenu(); 27 | private JFileChooser chooser; 28 | 29 | private File rootFile; 30 | private File readMe; 31 | private FileWriter readMeWrite; 32 | 33 | private Block block1; 34 | private Block block2; 35 | private Block block3; 36 | private Block block4; 37 | private Block block5; 38 | private Block block6; 39 | private Block block7; 40 | private Block block8; 41 | private Block block9; 42 | private Block block10; 43 | private ArrayList blocks = new ArrayList(); 44 | 45 | private JLabel blockName = new JLabel("Block Name:"); 46 | private JLabel nameField = new JLabel(); 47 | private JLabel haveUsed = new JLabel("Used:"); 48 | private JLabel usedField = new JLabel(); 49 | private JLabel freeYet = new JLabel("Free:"); 50 | private JLabel freeField = new JLabel(); 51 | private JLabel fileNum = new JLabel("Block's File Number:"); 52 | private JLabel fileNumField = new JLabel(); 53 | 54 | private JTextField searchLine = new JTextField(); 55 | 56 | private static String helpMessage = 57 | "" + 58 | "" + 59 | "

文件系统模拟

" + 60 | "

技术细节

" + 61 | "

显式链接(FAT)

" + 62 | "
  • 用一个专用文件记录分配和未分配的内存块
  • 使用链接的方式,不存在内存碎片
" + 63 | "

空闲空间管理 —— 位图

" + 64 | "
  • 用二进制0和1分别代表未分配的内存块和已经分配的内存块
  • 在该项目中位图和FAT进行了合并
" + 65 | "

目录结构 —— 多级目录结构

" + 66 | "

FCB

" + 67 | "
  • 文件类型
  • 文件名
  • 文件大小
  • 文件最近更新时间
" + 68 | "

操作说明

" + 69 | "
  • 必须先选择一个计算机上的文件夹作为模拟工作目录
  • 左侧树状结构即文件目录
  • 双击或点击文件夹左侧小图标可以打开文件目录
  • " + 70 | "
  • 右侧空白处为表格区域,将现实相关文件信息
  • 双击表格中的项可以直接打开相关文件
  • " + 71 | "
  • 下方绿色为盘信息面板,将现实相应盘的相应信息
  • " + 72 | "
  • 最下方空白处将显示内存块当前状况
" + 73 | "
  • 在树状结构中选中某一节点,右键即可选择相应的文件操作
  • " + 74 | "
  • 创建新的文件会要求输入文件名和文件大小(KB)
  • " + 75 | "

    特别说明

    " + 76 | "
    • 本程序重在模拟,并不是真正地为文件开了这么大的空间
    • 仅支持生成txt,文本文件中直接现实FCB,不支持修改内容
    • " + 77 | "
    • 对于非法输入都会直接导致文件生成失败
    • 如果存档文件recover.txt被破坏,将无法打开文件
    " + 78 | "" + 79 | ""; 80 | 81 | // Delete a dir 82 | public static void deleteDirectory(String filePath){ 83 | File file = new File(filePath); 84 | if(!file.exists()){ 85 | return; 86 | } 87 | if(file.isFile()){ 88 | file.delete(); 89 | }else if(file.isDirectory()){ 90 | File[] files = file.listFiles(); 91 | for (File myfile : files) { 92 | deleteDirectory(filePath + File.separator + myfile.getName()); 93 | } 94 | file.delete(); 95 | } 96 | } 97 | 98 | // Get space 99 | public double getSpace(File file){ 100 | double space = 0; 101 | try { 102 | BufferedReader reader = new BufferedReader(new FileReader(file)); 103 | reader.readLine(); 104 | space = Double.parseDouble(reader.readLine()); 105 | if (space > 1024){ 106 | space = 0.0; 107 | } 108 | reader.close(); 109 | } catch (Exception e){}; 110 | return space; 111 | } 112 | 113 | // Update block's information 114 | public void upDateBlock(Block currentBlock){ 115 | fileNumField.setText(String.valueOf(currentBlock.getFileNum())); 116 | usedField.setText(String.valueOf(currentBlock.getSpace()) + " KB"); 117 | freeField.setText(String.valueOf(1024 - currentBlock.getSpace()) + "KB"); 118 | } 119 | 120 | // Search a file 121 | public boolean searchFile(String fileName, File parent){ 122 | File [] files = parent.listFiles(); 123 | for (File myFile:files){ 124 | if (myFile.getName().equals(fileName)){ 125 | try { 126 | if(Desktop.isDesktopSupported()) { 127 | Desktop desktop = Desktop.getDesktop(); 128 | desktop.open(myFile); 129 | return true; 130 | } 131 | } catch (IOException e1) { 132 | JOptionPane.showMessageDialog(null, myFile.getPath() + " Sorry, some thing wrong!", "Fail to open", 133 | JOptionPane.ERROR_MESSAGE); 134 | return true; 135 | } 136 | } 137 | if (myFile.isDirectory() && myFile.canRead()){ 138 | if(searchFile(fileName, myFile)){ 139 | return true; 140 | } 141 | } 142 | } 143 | return false; 144 | } 145 | 146 | 147 | 148 | // Ui 149 | public UI() throws IOException { 150 | setTitle("File System Demo by 1452822 洪嘉勇"); 151 | setLayout(new BorderLayout()); 152 | setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 153 | 154 | // JFileChooser init 155 | String path = File.listRoots()[0].getPath(); 156 | String rootPath = new String(); 157 | chooser = new JFileChooser(path); 158 | chooser.setDialogTitle("Choose a dir for this demo"); 159 | chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 160 | chooser.setPreferredSize(new Dimension(800, 600)); 161 | int result = chooser.showOpenDialog(this); 162 | if (result == chooser.APPROVE_OPTION){ 163 | System.out.println(chooser.getSelectedFile().getAbsolutePath()); 164 | rootPath = chooser.getSelectedFile().getPath(); 165 | } 166 | 167 | // help init 168 | JLabel help = new JLabel(helpMessage); 169 | help.setFont(new Font("微软雅黑", Font.CENTER_BASELINE, 20)); 170 | JScrollPane helpPane = new JScrollPane(help); 171 | helpPane.setPreferredSize(new Dimension(500, 600)); 172 | JOptionPane.showMessageDialog(null, 173 | helpPane, 174 | "文件系统模拟", 175 | JOptionPane.DEFAULT_OPTION); 176 | 177 | // Create work space 178 | rootFile = new File(rootPath + File.separator + "myFileSystem"); 179 | readMe = new File(rootPath + File.separator + "myFileSystem" + File.separator + "ReadMe.txt"); 180 | 181 | boolean flag = true; 182 | 183 | // JTree init 184 | final DefaultMutableTreeNode root = new DefaultMutableTreeNode(new myFiles(rootFile, 0, 10240)); 185 | if (!rootFile.exists()) { 186 | flag = false; 187 | try { 188 | rootFile.mkdir(); 189 | readMe.createNewFile(); 190 | } catch (Exception e) { 191 | JOptionPane.showMessageDialog(null, "The place is not support to create dir!", "Error", JOptionPane.ERROR_MESSAGE); 192 | System.exit(0); 193 | } 194 | FileWriter writer = new FileWriter(readMe.getPath()); 195 | writer.write("Hello, this my file system!!!\n"); 196 | writer.write("Space: 10 * 1024K = 10M\n"); 197 | writer.write("Free-Space Management:bitmap\n"); 198 | writer.write("Store-Space Management:FAT\n"); 199 | writer.flush(); 200 | writer.close(); 201 | } 202 | 203 | block1 = new Block(1, new File(rootFile.getPath() + File.separator + "1"), flag); 204 | blocks.add(block1); 205 | block2 = new Block(2, new File(rootFile.getPath() + File.separator + "2"), flag); 206 | blocks.add(block2); 207 | block3 = new Block(3, new File(rootFile.getPath() + File.separator + "3"), flag); 208 | blocks.add(block3); 209 | block4 = new Block(4, new File(rootFile.getPath() + File.separator + "4"), flag); 210 | blocks.add(block4); 211 | block5 = new Block(5, new File(rootFile.getPath() + File.separator + "5"), flag); 212 | blocks.add(block5); 213 | block6 = new Block(6, new File(rootFile.getPath() + File.separator + "6"), flag); 214 | blocks.add(block6); 215 | block7 = new Block(7, new File(rootFile.getPath() + File.separator + "7"), flag); 216 | blocks.add(block7); 217 | block8 = new Block(8, new File(rootFile.getPath() + File.separator + "8"), flag); 218 | blocks.add(block8); 219 | block9 = new Block(9, new File(rootFile.getPath() + File.separator + "9"), flag); 220 | blocks.add(block9); 221 | block10 = new Block(10, new File(rootFile.getPath() + File.separator + "10"), flag); 222 | blocks.add(block10); 223 | 224 | root.add(new DefaultMutableTreeNode(new myFiles(block1.getBlockFile(), 1, 1024.0))); 225 | model.addRow(new myFiles(block1.getBlockFile(), 1, 1024.0)); 226 | ((DefaultMutableTreeNode)root.getChildAt(0)).add(new DefaultMutableTreeNode("temp")); 227 | 228 | root.add(new DefaultMutableTreeNode(new myFiles(block2.getBlockFile(), 2, 1024.0))); 229 | model.addRow(new myFiles(block2.getBlockFile(), 2, 1024.0)); 230 | ((DefaultMutableTreeNode)root.getChildAt(1)).add(new DefaultMutableTreeNode("temp")); 231 | 232 | root.add(new DefaultMutableTreeNode(new myFiles(block3.getBlockFile(), 3, 1024.0))); 233 | model.addRow(new myFiles(block3.getBlockFile(), 3, 1024.0)); 234 | ((DefaultMutableTreeNode)root.getChildAt(2)).add(new DefaultMutableTreeNode("temp")); 235 | 236 | root.add(new DefaultMutableTreeNode(new myFiles(block4.getBlockFile(), 4, 1024.0))); 237 | model.addRow(new myFiles(block4.getBlockFile(), 4, 1024.0)); 238 | ((DefaultMutableTreeNode)root.getChildAt(3)).add(new DefaultMutableTreeNode("temp")); 239 | 240 | root.add(new DefaultMutableTreeNode(new myFiles(block5.getBlockFile(), 5, 1024.0))); 241 | model.addRow(new myFiles(block5.getBlockFile(), 5, 1024.0)); 242 | ((DefaultMutableTreeNode)root.getChildAt(4)).add(new DefaultMutableTreeNode("temp")); 243 | 244 | root.add(new DefaultMutableTreeNode(new myFiles(block6.getBlockFile(), 6, 1024.0))); 245 | model.addRow(new myFiles(block6.getBlockFile(), 6, 1024.0)); 246 | ((DefaultMutableTreeNode)root.getChildAt(5)).add(new DefaultMutableTreeNode("temp")); 247 | 248 | root.add(new DefaultMutableTreeNode(new myFiles(block7.getBlockFile(), 7, 1024.0))); 249 | model.addRow(new myFiles(block7.getBlockFile(), 7, 1024.0)); 250 | ((DefaultMutableTreeNode)root.getChildAt(6)).add(new DefaultMutableTreeNode("temp")); 251 | 252 | root.add(new DefaultMutableTreeNode(new myFiles(block8.getBlockFile(), 8, 1024.0))); 253 | model.addRow(new myFiles(block8.getBlockFile(), 8, 1024.0)); 254 | ((DefaultMutableTreeNode)root.getChildAt(7)).add(new DefaultMutableTreeNode("temp")); 255 | 256 | root.add(new DefaultMutableTreeNode(new myFiles(block9.getBlockFile(), 9, 1024.0))); 257 | model.addRow(new myFiles(block9.getBlockFile(), 9, 1024.0)); 258 | ((DefaultMutableTreeNode)root.getChildAt(8)).add(new DefaultMutableTreeNode("temp")); 259 | 260 | root.add(new DefaultMutableTreeNode(new myFiles(block10.getBlockFile(), 10, 1024.0))); 261 | model.addRow(new myFiles(block10.getBlockFile(), 10, 1024.0)); 262 | ((DefaultMutableTreeNode)root.getChildAt(9)).add(new DefaultMutableTreeNode("temp")); 263 | 264 | root.add(new DefaultMutableTreeNode(new myFiles(readMe, 0, 0))); 265 | model.addRow(new myFiles(readMe, 0, 0)); 266 | 267 | // Table init 268 | fileTable = new JTable(model); 269 | fileTable.getTableHeader().setFont(new Font(Font.DIALOG,Font.CENTER_BASELINE,24)); 270 | fileTable.setSelectionBackground(Color.ORANGE); 271 | 272 | fileTable.updateUI(); 273 | 274 | final DefaultTreeModel treeModel = new DefaultTreeModel(root); 275 | tree = new JTree(treeModel); 276 | tree.setEditable(false); 277 | tree.putClientProperty("Jtree.lineStyle", "Horizontal"); 278 | tree.getSelectionModel().setSelectionMode 279 | (TreeSelectionModel.SINGLE_TREE_SELECTION); 280 | tree.setShowsRootHandles(true); 281 | tree.addTreeSelectionListener(new TreeSelectionListener() { 282 | @Override 283 | public void valueChanged(TreeSelectionEvent e) { 284 | DefaultMutableTreeNode parent = null; 285 | TreePath parentPath = e.getPath(); 286 | if (parentPath == null){ 287 | parent = root; 288 | }else{ 289 | parent = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); 290 | } 291 | int blokName = ((myFiles)parent.getUserObject()).getBlockName(); 292 | Block currentBlock = blocks.get(blokName - 1); 293 | if (parentPath == null){ 294 | parent = root; 295 | }else{ 296 | parent = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); 297 | } 298 | 299 | nameField.setText(String.valueOf(blokName)); 300 | upDateBlock(currentBlock); 301 | 302 | model.removeRows(0, model.getRowCount()); 303 | File rootFile = new File(((myFiles)parent.getUserObject()).getFilePath()); 304 | if (parent.getChildCount() > 0) { 305 | File[] childFiles = rootFile.listFiles(); 306 | 307 | for (File file : childFiles) { 308 | model.addRow(new myFiles(file, blokName, getSpace(file))); 309 | } 310 | } 311 | else{ 312 | model.addRow(new myFiles(rootFile, blokName, getSpace(rootFile))); 313 | } 314 | fileTable.updateUI(); 315 | 316 | } 317 | }); 318 | tree.addTreeWillExpandListener(new TreeWillExpandListener() { 319 | @Override 320 | public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException { 321 | DefaultMutableTreeNode parent = null; 322 | TreePath parentPath = event.getPath(); 323 | if (parentPath == null){ 324 | parent = root; 325 | }else{ 326 | parent = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); 327 | } 328 | 329 | int blokName = ((myFiles)parent.getUserObject()).getBlockName(); 330 | 331 | File rootFile = new File(((myFiles)parent.getUserObject()).getFilePath()); 332 | File [] childFiles = rootFile.listFiles(); 333 | 334 | model.removeRows(0, model.getRowCount()); 335 | for (File myFile : childFiles){ 336 | DefaultMutableTreeNode node = null; 337 | node = new DefaultMutableTreeNode(new myFiles(myFile, blokName, getSpace(myFile))); 338 | if (myFile.isDirectory() && myFile.canRead()) { 339 | node.add(new DefaultMutableTreeNode("temp")); 340 | } 341 | 342 | treeModel.insertNodeInto(node, parent,parent.getChildCount()); 343 | model.addRow(new myFiles(myFile, blokName, getSpace(myFile))); 344 | } 345 | if (parent.getChildAt(0).toString().equals("temp") && parent.getChildCount() != 1) 346 | treeModel.removeNodeFromParent((MutableTreeNode) parent.getChildAt(0)); 347 | fileTable.updateUI(); 348 | } 349 | 350 | @Override 351 | public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException { 352 | DefaultMutableTreeNode parent = null; 353 | TreePath parentPath = event.getPath(); 354 | if (parentPath == null){ 355 | parent = root; 356 | }else{ 357 | parent = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); 358 | } 359 | if (parent.getChildCount() > 0) { 360 | int count = parent.getChildCount(); 361 | for (int i = count - 1; i >= 0; i--){ 362 | treeModel.removeNodeFromParent((MutableTreeNode) parent.getChildAt(i)); 363 | } 364 | treeModel.insertNodeInto(new DefaultMutableTreeNode("temp"), parent,parent.getChildCount()); 365 | } 366 | model.removeRows(0, model.getRowCount()); 367 | fileTable.updateUI(); 368 | } 369 | }); 370 | treePane = new JScrollPane(tree); 371 | treePane.setPreferredSize(new Dimension(150, 400)); 372 | add(treePane, BorderLayout.WEST); 373 | 374 | tablePane = new JScrollPane(fileTable); 375 | add(tablePane, BorderLayout.CENTER); 376 | 377 | 378 | // Mouse DoubleClick to open a file 379 | fileTable.addMouseListener(new MouseAdapter() { 380 | @Override 381 | public void mouseClicked(MouseEvent e) { 382 | super.mouseClicked(e); 383 | if (e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1){ 384 | String fileName = ((String) model.getValueAt(fileTable.getSelectedRow(), 0)); 385 | String filePath = ((String) model.getValueAt(fileTable.getSelectedRow(), 1)); 386 | try { 387 | if(Desktop.isDesktopSupported()) { 388 | Desktop desktop = Desktop.getDesktop(); 389 | desktop.open(new File(filePath)); 390 | } 391 | } catch (IOException e1) { 392 | JOptionPane.showMessageDialog(null, "Sorry, some thing wrong!", "Fail to open", 393 | JOptionPane.ERROR_MESSAGE); 394 | } 395 | JOptionPane.showMessageDialog(null, "File Name: " + fileName + "\n File Path: " + filePath, "content", 396 | JOptionPane.INFORMATION_MESSAGE); 397 | } 398 | } 399 | }); 400 | 401 | // Menu init 402 | final JPopupMenu myMenu = new JPopupMenu(); 403 | myMenu.setPreferredSize(new Dimension(300, 200)); 404 | 405 | // Create a file and update fileTable to show it 406 | JMenuItem createFileItem = new JMenuItem("create a file"); 407 | createFileItem.addActionListener(new ActionListener() { 408 | @Override 409 | public void actionPerformed(ActionEvent e) { 410 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 411 | myFiles temp = (myFiles)node.getUserObject(); 412 | int blokName = temp.getBlockName(); 413 | Block currentBlock = blocks.get(blokName - 1); 414 | 415 | String inputValue; 416 | double capacity; 417 | 418 | JOptionPane inputPane = new JOptionPane(); 419 | inputPane.setPreferredSize(new Dimension(600, 600)); 420 | inputPane.setInputValue(JOptionPane.showInputDialog("File name:")); 421 | if (inputPane.getInputValue() == null) { 422 | return; 423 | } 424 | inputValue = inputPane.getInputValue().toString(); 425 | inputPane.setInputValue(JOptionPane.showInputDialog("Large(KB):")); 426 | if (inputPane.getInputValue() == null) { 427 | return; 428 | } 429 | capacity = Double.parseDouble(inputPane.getInputValue().toString()); 430 | 431 | File newFile = new File(temp.getFilePath() + File.separator + inputValue + ".txt"); 432 | if (!newFile.exists() && !inputValue.equals(null)){ 433 | try { 434 | if (currentBlock.createFile(newFile, capacity)) { 435 | DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(new myFiles(newFile, blokName, capacity)); 436 | model.removeRows(0, model.getRowCount()); 437 | model.addRow(new myFiles(newFile, blokName, capacity)); 438 | fileTable.updateUI(); 439 | upDateBlock(currentBlock); 440 | JOptionPane.showMessageDialog(null, "Create success! Reopen the parent dir to reflash!", "Success", JOptionPane.DEFAULT_OPTION); 441 | } 442 | } catch (IOException e1) { 443 | JOptionPane.showMessageDialog(null, "Create fail!!!", "Error", JOptionPane.ERROR_MESSAGE); 444 | } 445 | } 446 | } 447 | }); 448 | myMenu.add(createFileItem); 449 | 450 | // create a dir and update fileTable to show it 451 | JMenuItem createDirItem = new JMenuItem("create a dir"); 452 | createDirItem.addActionListener(new ActionListener() { 453 | @Override 454 | public void actionPerformed(ActionEvent e) { 455 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 456 | myFiles temp = (myFiles)node.getUserObject(); 457 | int blokName = temp.getBlockName(); 458 | Block currentBlock = blocks.get(blokName - 1); 459 | String inputValue = JOptionPane.showInputDialog("Dir name:"); 460 | if (inputValue == null) { 461 | return; 462 | } 463 | File newDir = new File(temp.getFilePath() + File.separator + inputValue); 464 | if (newDir.exists()) 465 | deleteDirectory(newDir.getPath()); 466 | try{ 467 | newDir.mkdir(); 468 | DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(new myFiles(newDir, blokName, 0)); 469 | newNode.add(new DefaultMutableTreeNode("temp")); 470 | model.removeRows(0, model.getRowCount()); 471 | model.addRow(new myFiles(newDir, blokName, 0)); 472 | fileTable.updateUI(); 473 | upDateBlock(currentBlock); 474 | JOptionPane.showMessageDialog(null, "Create success! Reopen the parent dir to reflash!", "Success", JOptionPane.DEFAULT_OPTION); 475 | }catch (Exception E){ 476 | JOptionPane.showMessageDialog(null, "Create fail!!!", "Error", JOptionPane.ERROR_MESSAGE); 477 | } 478 | } 479 | }); 480 | myMenu.add(createDirItem); 481 | 482 | // Delete a file or a dir 483 | JMenuItem deleteItem = new JMenuItem("delete"); 484 | deleteItem.addActionListener(new ActionListener() { 485 | @Override 486 | public void actionPerformed(ActionEvent e) { 487 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 488 | myFiles temp = (myFiles)node.getUserObject(); 489 | int blokName = temp.getBlockName(); 490 | Block currentBlock = blocks.get(blokName - 1); 491 | int choose = JOptionPane.showConfirmDialog(null, "Are you sure to delete this file/dir?", "confirm", JOptionPane.YES_NO_OPTION); 492 | if (choose == 0){ 493 | if (currentBlock.deleteFile(temp.getMyFile(), temp.getSpace())){ 494 | try { 495 | currentBlock.rewriteBitMap(); 496 | currentBlock.rewriteRecoverWriter(); 497 | } catch (IOException e1) { 498 | e1.printStackTrace(); 499 | } 500 | upDateBlock(currentBlock); 501 | JOptionPane.showMessageDialog(null, "Delete success! Reopen the parent dir to reflash!", "Success", JOptionPane.DEFAULT_OPTION); 502 | }else{ 503 | JOptionPane.showMessageDialog(null, "Delete fail!!!", "Error", JOptionPane.ERROR_MESSAGE); 504 | } 505 | } 506 | } 507 | }); 508 | myMenu.add(deleteItem); 509 | 510 | // Format a dir 511 | JMenuItem formatItem = new JMenuItem("format"); 512 | formatItem.addActionListener(new ActionListener() { 513 | @Override 514 | public void actionPerformed(ActionEvent e) { 515 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 516 | myFiles temp = (myFiles)node.getUserObject(); 517 | int blokName = temp.getBlockName(); 518 | Block currentBlock = blocks.get(blokName - 1); 519 | int choose = JOptionPane.showConfirmDialog(null, "Are you sure to format this dir?", "confirm", JOptionPane.YES_NO_OPTION); 520 | if (choose == 0){ 521 | try{ 522 | if (temp.getMyFile().isDirectory()) { 523 | for (File myfile : temp.getMyFile().listFiles()) { 524 | currentBlock.deleteFile(myfile, getSpace(myfile)); 525 | } 526 | upDateBlock(currentBlock); 527 | JOptionPane.showMessageDialog(null, "Format success! Reopen the parent dir to reflash!", "Success", JOptionPane.DEFAULT_OPTION); 528 | currentBlock.rewriteBitMap(); 529 | } 530 | }catch (Exception E1){ 531 | JOptionPane.showMessageDialog(null, "Format fail!!!", "Error", JOptionPane.ERROR_MESSAGE); 532 | } 533 | } 534 | } 535 | }); 536 | myMenu.add(formatItem); 537 | 538 | // Rename a dir/file 539 | JMenuItem renameItem = new JMenuItem("rename"); 540 | // renameItem.setFont(new Font("微软雅黑",Font.CENTER_BASELINE,24)); 541 | renameItem.addActionListener(new ActionListener() { 542 | @Override 543 | public void actionPerformed(ActionEvent e) { 544 | DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent(); 545 | myFiles temp = (myFiles)node.getUserObject(); 546 | int blokName = temp.getBlockName(); 547 | Block currentBlock = blocks.get(blokName - 1); 548 | 549 | String inputValue = null; 550 | JOptionPane inputPane = new JOptionPane(); 551 | inputPane.setInputValue(JOptionPane.showInputDialog("New file name:")); 552 | if (inputPane.getInputValue() == null) { 553 | return; 554 | } 555 | inputValue = inputPane.getInputValue().toString(); 556 | try { 557 | currentBlock.renameFile(temp.getMyFile(), inputValue, temp.getSpace()); 558 | JOptionPane.showMessageDialog(null, "Rename success! Reopen the parent dir to reflash!", "Success", JOptionPane.DEFAULT_OPTION); 559 | } catch (IOException e1) { 560 | JOptionPane.showMessageDialog(null, "Rename fail!!!", "Error", JOptionPane.ERROR_MESSAGE); 561 | } 562 | } 563 | }); 564 | myMenu.add(renameItem); 565 | 566 | // Information for the block 567 | JPanel panel = new JPanel(); 568 | panel.setBackground(Color.green); 569 | panel.setLayout(new FlowLayout(FlowLayout.CENTER)); 570 | JLabel tips = new JLabel("文件操作:选中左侧文件之后右键 打开文件:双击右侧表格内文件"); 571 | panel.add(tips); 572 | panel.add(blockName); 573 | nameField.setForeground(Color.RED); 574 | panel.add(nameField); 575 | panel.add(new JLabel(" ")); 576 | panel.add(haveUsed); 577 | usedField.setForeground(Color.RED); 578 | panel.add(usedField); 579 | panel.add(new JLabel(" ")); 580 | panel.add(freeYet); 581 | freeField.setForeground(Color.RED); 582 | panel.add(freeField); 583 | panel.add(new JLabel(" ")); 584 | panel.add(fileNum); 585 | fileNumField.setForeground(Color.RED); 586 | panel.add(fileNumField); 587 | add(panel, BorderLayout.SOUTH); 588 | 589 | 590 | // SeachLine init 591 | JPanel searchPane = new JPanel(new FlowLayout(FlowLayout.LEFT)); 592 | final JLabel searchLabel = new JLabel("Search(eg. File:hehe.txt Dir:hehe): "); 593 | searchPane.add(searchLabel); 594 | searchLine.setPreferredSize(new Dimension(500, 50)); 595 | searchPane.add(searchLine); 596 | JButton searchButton = new JButton("start"); 597 | searchButton.addActionListener(new ActionListener() { 598 | @Override 599 | public void actionPerformed(ActionEvent e) { 600 | String fileName = searchLine.getText(); 601 | if(!searchFile(fileName, rootFile)){ 602 | JOptionPane.showMessageDialog(null, "Can not find this file!", "Fail!", JOptionPane.WARNING_MESSAGE); 603 | } 604 | searchLine.setText(""); 605 | } 606 | }); 607 | searchPane.add(searchButton); 608 | add(searchPane, BorderLayout.NORTH); 609 | 610 | // Listen to the tree 611 | tree.addMouseListener(new MouseAdapter() { 612 | @Override 613 | public void mouseClicked(MouseEvent e) { 614 | super.mouseClicked(e); 615 | if (e.getButton() == MouseEvent.BUTTON3){ 616 | myMenu.show(e.getComponent(), e.getX(), e.getY()); 617 | 618 | } 619 | } 620 | }); 621 | 622 | setSize(1200, 600); 623 | setVisible(true); 624 | } 625 | 626 | public static void main(String args[]) throws IOException { 627 | new UI(); 628 | } 629 | } 630 | --------------------------------------------------------------------------------