最近发现磁盘空间严重不足,都弹窗提示我了:
想想看到底哪个文件夹占的空间比较大,好做针对性的删除和清理。奈何Windows系统没有查看文件夹大小的工具,只能鼠标放在某个文件夹上,等提示:
AI时代都来临了,就让ChatGPT帮我写一个程序吧:计算指定文件夹中所有文件夹的大小并排序。
初版
于是,我就向ChatGPT提问:
完整的代码是这样的:
importjava.io.File;importjava.util.ArrayList;importjava.util.Collections;importjava.util.Comparator;publicclassFolderSizeCalculator{publicstaticvoidmain(String[] args){// 指定文件夹路径String folderPath ="/path/to/folder";// 获取文件夹列表File folder =newFile(folderPath);File[] folderList = folder.listFiles(File::isDirectory);// 计算每个文件夹的大小并存储到ArrayList中ArrayList<Folder> folders =newArrayList<>();for(File f : folderList){long size =getFolderSize(f);Folder folderObj =newFolder(f.getName(), size);
folders.add(folderObj);}// 根据文件夹大小进行排序Collections.sort(folders,Comparator.comparingLong(Folder::getSize));// 输出结果for(Folder f : folders){System.out.println(f.getName()+" - "+formatSize(f.getSize()));}}// 递归计算文件夹大小publicstaticlonggetFolderSize(File folder){long size =0;File[] fileList = folder.listFiles();if(fileList !=null){for(File f : fileList){if(f.isFile()){
size += f.length();}else{
size +=getFolderSize(f);}}}return size;}// 格式化文件大小publicstaticStringformatSize(long size){String[] units ={"B","KB","MB","GB","TB"};int i =0;double s = size;while(s >=1024&& i < units.length -1){
s /=1024;
i++;}returnString.format("%.2f %s", s, units[i]);}}// 文件夹类classFolder{privateString name;privatelong size;publicFolder(String name,long size){this.name = name;this.size = size;}publicStringgetName(){return name;}publiclonggetSize(){return size;}}
使用
File
类获取指定文件夹中的所有子文件夹,然后使用递归函数
getFolderSize
计算每个文件夹的大小,最后将结果存储到一个
ArrayList
中。程序使用
Collections.sort
方法根据文件夹大小对
ArrayList
进行排序,并使用
formatSize
方法格式化文件大小并输出结果。
修改一下指定文件夹的路径就可以运行,效果还不错:
社 - 646.13 KB
学 - 141.15 MB
猫 - 587.99 MB
万 - 1.52 GB
唯一有一点小瑕疵,排序是从小到大的,稍微做一下修改,把
// 根据文件夹大小进行排序Collections.sort(folders,Comparator.comparingLong(Folder::getSize));
修改为:
// 根据文件夹大小进行排序Collections.sort(folders,(f1, f2)->Long.compare(f2.getSize(), f1.getSize()));
运行一下,看看效果:
万 - 1.52 GB
猫 - 587.99 MB
学 - 141.15 MB
社 - 646.13 KB
进化
每次修改需要计算的文件夹路径时,都需要修改代码重新运行,很不方便。我想到了Swing,可以用UI进行交互。于是,我又向ChatGPT重新提问:
完整的代码如下:
importjava.awt.*;importjava.awt.event.*;importjava.io.*;importjava.util.*;importjavax.swing.*;publicclassFolderSizeSorterextendsJFrame{privateJLabel directoryLabel;privateJTextField directoryTextField;privateJButton calculateButton;privateJTextArea resultTextArea;publicFolderSizeSorter(){super("Folder Size Sorter");// set up UI components
directoryLabel =newJLabel("Directory:");
directoryTextField =newJTextField(20);
calculateButton =newJButton("Calculate");
resultTextArea =newJTextArea(20,40);JScrollPane scrollPane =newJScrollPane(resultTextArea);// set up layoutJPanel inputPanel =newJPanel();
inputPanel.add(directoryLabel);
inputPanel.add(directoryTextField);
inputPanel.add(calculateButton);add(inputPanel,BorderLayout.NORTH);add(scrollPane,BorderLayout.CENTER);// set up event listeners
calculateButton.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvent e){calculateFolderSizes();}});// set up window propertiessetDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setSize(500,400);setVisible(true);}privatevoidcalculateFolderSizes(){String directoryPath = directoryTextField.getText();File directory =newFile(directoryPath);if(!directory.isDirectory()){JOptionPane.showMessageDialog(this,"Please enter a valid directory path.");return;}Map<File,Long> folderSizes =newHashMap<>();calculateFolderSizesRecursive(directory, folderSizes);List<Map.Entry<File,Long>> folderSizesList =newArrayList<>(folderSizes.entrySet());Collections.sort(folderSizesList,newComparator<Map.Entry<File,Long>>(){publicintcompare(Map.Entry<File,Long> o1,Map.Entry<File,Long> o2){return o2.getValue().compareTo(o1.getValue());}});
resultTextArea.setText("");for(Map.Entry<File,Long> folderSize : folderSizesList){
resultTextArea.append(folderSize.getKey().getPath()+" - "+formatSize(folderSize.getValue())+"\n");}}privatevoidcalculateFolderSizesRecursive(File folder,Map<File,Long> folderSizes){File[] files = folder.listFiles();if(files ==null){return;}long folderSize =0;for(File file : files){if(file.isDirectory()){calculateFolderSizesRecursive(file, folderSizes);
folderSize += folderSizes.get(file);}else{
folderSize += file.length();}}
folderSizes.put(folder, folderSize);}privateStringformatSize(long size){String[] units ={"B","KB","MB","GB","TB"};int unitIndex =0;double dSize = size;while(dSize >=1024&& unitIndex < units.length -1){
dSize /=1024;
unitIndex++;}returnString.format("%.2f %s", dSize, units[unitIndex]);}publicstaticvoidmain(String[] args){newFolderSizeSorter();}}
创建了一个GUI窗口,包括一个标签、一个文本框、一个按钮,在文本框输入文件夹的路径,点击“Calculate”就可以了,效果如下图:
再进化
在使用过程中,又有了新的问题:我看到某一个文件夹比较大,想再看看这个文件夹下的文件夹大小情况,还得手动复制粘贴文件夹路径重新计算,操作起来不是很方便。于是,我又向ChatGPT重新提问:
完整的代码如下:
importjava.awt.BorderLayout;importjava.awt.EventQueue;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.io.File;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importjavax.swing.JButton;importjavax.swing.JFileChooser;importjavax.swing.JFrame;importjavax.swing.JPanel;importjavax.swing.JScrollPane;importjavax.swing.JTree;importjavax.swing.tree.DefaultMutableTreeNode;importjavax.swing.tree.DefaultTreeModel;publicclassFolderSizeCalculatorextendsJFrame{privatestaticfinallong serialVersionUID =1L;privateJPanel contentPane;privateJButton btnSelectFolder;privateJTree tree;privateDefaultTreeModel treeModel;/**
* Launch the application.
*/publicstaticvoidmain(String[] args){EventQueue.invokeLater(newRunnable(){publicvoidrun(){try{FolderSizeCalculator frame =newFolderSizeCalculator();
frame.setVisible(true);}catch(Exception e){
e.printStackTrace();}}});}/**
* Create the frame.
*/publicFolderSizeCalculator(){setTitle("Folder Size Calculator");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,450,300);
contentPane =newJPanel();
contentPane.setLayout(newBorderLayout(0,0));setContentPane(contentPane);
btnSelectFolder =newJButton("Select Folder");
btnSelectFolder.addActionListener(newActionListener(){publicvoidactionPerformed(ActionEvent e){JFileChooser fileChooser =newJFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);int result = fileChooser.showOpenDialog(FolderSizeCalculator.this);if(result ==JFileChooser.APPROVE_OPTION){File folder = fileChooser.getSelectedFile();DefaultMutableTreeNode root =newDefaultMutableTreeNode(folder.getName());
treeModel =newDefaultTreeModel(root);
tree.setModel(treeModel);calculateFolderSize(folder, root);
tree.expandRow(0);}}});
contentPane.add(btnSelectFolder,BorderLayout.NORTH);JScrollPane scrollPane =newJScrollPane();
contentPane.add(scrollPane,BorderLayout.CENTER);
tree =newJTree();
scrollPane.setViewportView(tree);}privatevoidcalculateFolderSize(File folder,DefaultMutableTreeNode node){long size =0;List<File> subfolders =newArrayList<>();for(File file : folder.listFiles()){if(file.isDirectory()){
subfolders.add(file);}else{
size += file.length();}}Collections.sort(subfolders);for(File subfolder : subfolders){DefaultMutableTreeNode subnode =newDefaultMutableTreeNode(subfolder.getName());
node.add(subnode);calculateFolderSize(subfolder, subnode);}
node.setUserObject(node.getUserObject()+" ("+humanReadableByteCount(size,false)+")");}privateStringhumanReadableByteCount(long bytes,boolean si){int unit = si ?1000:1024;if(bytes < unit)return bytes +" B";int exp =(int)(Math.log(bytes)/Math.log(unit));String pre =(si ?"kMGTPE":"KMGTPE").charAt(exp -1)+(si ?"":"i");returnString.format("%.1f %sB", bytes /Math.pow(unit, exp), pre);}}
这个程序中,创建了一个继承自
JFrame
的
FolderSizeCalculator
类,并在其中创建了一个用户界面。
我们可以通过点击“Select Folder”按钮来选择要计算大小的文件夹。一旦用户选择了一个文件夹,程序将会计算该文件夹中所有文件夹的大小,并将结果以树形结构展示出来。
计算文件夹大小的方法是
calculateFolderSize
,它使用递归来遍历文件夹及其子文件夹,计算它们的大小。该方法将每个子文件夹作为一个节点添加到树中,并将文件夹大小添加到节点名称中。
humanReadableByteCount
是一个辅助方法,用于将文件大小从字节转换为人类可读的格式(如MB、GB等)。
运行一下,看看效果:
发现了问题,子文件夹的大小反而比父文件夹的大,仔细阅读了一下代码发现:在
calculateFolderSize
方法中累加了文件的大小,没有累加子文件夹的大小。于是,我又向ChatGPT重新提问:
ChatGPT增加了一个
calculateTotalSize
方法:
privatelongcalculateTotalSize(File folder){long totalSize =0;if(folder.isDirectory()){for(File file : folder.listFiles()){if(file.isDirectory()){
totalSize +=calculateTotalSize(file);}else{
totalSize += file.length();}}}else{
totalSize = folder.length();}return totalSize;}
在该方法中,首先检查传递的文件夹是否是文件夹类型。如果是文件夹,则迭代遍历其所有子项,如果子项是文件夹,则递归调用该方法以计算其大小;如果子项是文件,则将其大小加到总大小中。如果传递的文件夹是文件,则直接返回其大小。最终,该方法返回总大小。
将以上方法集成到原有方法中,用于计算文件夹下所有文件和文件夹的大小总和。以下是修改后的示例代码:
privatevoidcalculateFolderSize(File folder,DefaultMutableTreeNode node){long size =calculateTotalSize(folder);List<File> subfolders =newArrayList<>();for(File file : folder.listFiles()){if(file.isDirectory()){
subfolders.add(file);}}Collections.sort(subfolders);for(File subfolder : subfolders){DefaultMutableTreeNode subnode =newDefaultMutableTreeNode(subfolder.getName());
node.add(subnode);calculateFolderSize(subfolder, subnode);}
node.setUserObject(node.getUserObject()+" ("+humanReadableByteCount(size,false)+")");}
我们可以发现ChatGPT修改后的代码性能不是很好,因为
calculateFolderSize
方法就是一个递归方法,在这个递归方法里还要对每个文件夹再做一次递归。
我们完全可以在一次递归中完成整个计算过程。于是,我又向ChatGPT重新提问:
很遗憾,我虽然给ChatGPT扣上了卓越的帽子,但回答仍然不理想。
只能自己动手了,把
calculateFolderSize
方法修改为:
privatelongcalculateFolderSize(File folder,DefaultMutableTreeNode node){long size =0;Map<DefaultMutableTreeNode,Long> nodeMap =newHashMap<>();for(File file : folder.listFiles()){if(file.isDirectory()){DefaultMutableTreeNode subnode =newDefaultMutableTreeNode(file.getName());long subSize =calculateFolderSize(file, subnode);
nodeMap.put(subnode, subSize);
size += subSize;}else{
size += file.length();}}List<Entry<DefaultMutableTreeNode,Long>> nodes =newArrayList<>(nodeMap.entrySet());Collections.sort(nodes,(o1,o2)-> o2.getValue().compareTo(o1.getValue()));for(Map.Entry<DefaultMutableTreeNode,Long> entry : nodes){
node.add(entry.getKey());}
node.setUserObject(node.getUserObject()+" ("+humanReadableByteCount(size,false)+")");return size;}
运行一下,看看效果:
结尾
自从ChatGPT等AI技术风靡全球以来,有不少人开始担忧:我会不会被AI所替代?虽然AI在许多领域展现出了惊人的能力,但要想完全替代人类仍需克服许多难题。
在本文中,即便是在AI目前已经显示出较高的技术水平下,它仍然需要我的改进和优化来完成我所提供的任务。AI可以被看作是一种工具,协助我解决一些复杂的问题,提高工作效率。
因此,替代你的并不是AI,而是那些能够运用AI的人。
附:最终完整代码
importjavax.swing.*;importjavax.swing.tree.DefaultMutableTreeNode;importjavax.swing.tree.DefaultTreeModel;importjava.awt.*;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.io.File;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjava.util.Map.Entry;publicclassFolderSizeCalculatorextendsJFrame{privatestaticfinallong serialVersionUID =1L;privateJPanel contentPane;privateJButton btnSelectFolder;privateJTree tree;privateDefaultTreeModel treeModel;/**
* Launch the application.
*/publicstaticvoidmain(String[] args){EventQueue.invokeLater(()->{try{FolderSizeCalculator frame =newFolderSizeCalculator();
frame.setVisible(true);}catch(Exception e){
e.printStackTrace();}});}/**
* Create the frame.
*/publicFolderSizeCalculator(){setTitle("Folder Size Calculator");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setBounds(100,100,450,300);
contentPane =newJPanel();
contentPane.setLayout(newBorderLayout(0,0));setContentPane(contentPane);
btnSelectFolder =newJButton("Select Folder");
btnSelectFolder.addActionListener(newActionListener(){@OverridepublicvoidactionPerformed(ActionEvent e){JFileChooser fileChooser =newJFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);int result = fileChooser.showOpenDialog(FolderSizeCalculator.this);if(result ==JFileChooser.APPROVE_OPTION){File folder = fileChooser.getSelectedFile();DefaultMutableTreeNode root =newDefaultMutableTreeNode(folder.getName());
treeModel =newDefaultTreeModel(root);
tree.setModel(treeModel);calculateFolderSize(folder, root);
tree.expandRow(0);}}});
contentPane.add(btnSelectFolder,BorderLayout.NORTH);JScrollPane scrollPane =newJScrollPane();
contentPane.add(scrollPane,BorderLayout.CENTER);
tree =newJTree();
scrollPane.setViewportView(tree);}privatelongcalculateFolderSize(File folder,DefaultMutableTreeNode node){long size =0;Map<DefaultMutableTreeNode,Long> nodeMap =newHashMap<>();for(File file : folder.listFiles()){if(file.isDirectory()){DefaultMutableTreeNode subnode =newDefaultMutableTreeNode(file.getName());long subSize =calculateFolderSize(file, subnode);
nodeMap.put(subnode, subSize);
size += subSize;}else{
size += file.length();}}List<Entry<DefaultMutableTreeNode,Long>> nodes =newArrayList<>(nodeMap.entrySet());
nodes.sort((o1, o2)-> o2.getValue().compareTo(o1.getValue()));for(Map.Entry<DefaultMutableTreeNode,Long> entry : nodes){
node.add(entry.getKey());}
node.setUserObject(node.getUserObject()+" ("+humanReadableByteCount(size,false)+")");return size;}privateStringhumanReadableByteCount(long bytes,boolean si){int unit = si ?1000:1024;if(bytes < unit){return bytes +" B";}int exp =(int)(Math.log(bytes)/Math.log(unit));String pre =(si ?"kMGTPE":"KMGTPE").charAt(exp -1)+(si ?"":"i");returnString.format("%.1f %sB", bytes /Math.pow(unit, exp), pre);}}
版权归原作者 万猫学社 所有, 如有侵权,请联系我们删除。