利用Java获取磁盘基本信息

之前想写一个小的练手项目的时候突然有对这个的需求,但是网上全是到处搬运的错误的、不完整的代码,要不就是只给列个根目录出来…最后找了半天发现JDK本身就支持这个,于是就写出来分享一下。

完整代码

仅展示测试代码,实际使用时可能还需要改动。 测试环境:

  • 操作系统:Windows 10 22H2
  • Java版本:17
  • JDK:GraalVM 17.0.7+8.1(Hotspot模式)
package main;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.HashMap;

/**
 * 使用Java获取磁盘基本信息.
 * @author Denvo
 */
public class Main {
    public static void main(String[] args) {
        System.out.print("\n");
        Iterable roots = FileSystems.getDefault().getRootDirectories(); //获取所有的磁盘的根目录.
        for (Path root:roots) {
            System.out.println(root.toString() + "信息:" + getDiskInfo(root)); //getDiskInfo()方法在下面实现.
        }
    }

    /**
     * 根据卷根目录获取卷的信息.
     * @param root 根目录,如"C:\","D:\"
     * @return 包含卷的信息的HashMap.
     */
    private static HashMap getDiskInfo(Path root) {
        HashMap result = new HashMap(8);
        try {
            FileStore fs = Files.getFileStore(root);
            result.put("卷标",fs.name());
            result.put("文件存储类型",fs.type());
            result.put("只读",String.valueOf(fs.isReadOnly()));
            result.put("总容量",autoUnitConversion(fs.getTotalSpace())); //autoUnitConversion()方法在下面实现.
            result.put("可用容量",autoUnitConversion(fs.getUsableSpace()));
            result.put("每个扇区大小",fs.getBlockSize() + " Bytes");
            //以下仅Windows可用.
            result.put("可移动",fs.getAttribute("volume:isRemovable").toString());
            result.put("是否为CD-ROM",fs.getAttribute("volume:isCdrom").toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 单位转换,从Byte转换成Byte,KB,MB,GB,TB,PB,EB等.
     * @param bytesSize 原始大小(Byte)
     * @return 换算之后的大小(自动添加单位)
     */
    private static String autoUnitConversion(long bytesSize) {
        if (bytesSize < 0) {
            return "0";
        } else {
            double before = bytesSize;
            double after;
            for (int i = 0; i < 7; i++) {
                after = before / 1024;
                if (after < 1) {
                    String unit = switch (i) {
                        case 0 -> " Bytes";
                        case 1 -> " KB";
                        case 2 -> " MB";
                        case 3 -> " GB";
                        case 4 -> " TB";
                        case 5 -> " PB";
                        case 6 -> " EB";
                        default -> null;
                    };
                    return new DecimalFormat("#.##").format(before) + unit; //这里设置保留2位小数.
                } else {
                    before = after;
                }
            }
            return "8 EB或更大"; //long类型的最大值换算过来最大只有8EB.(正常情况下都应该从上面for循环中return.)
        }
    }
}

代码运行结果

我的电脑目前的磁盘有如下,其中G盘到J盘都是U盘。

在Explorer中看到的磁盘

以上代码的运行结果如下:



C:\信息:{文件存储类型=NTFS, 总容量=223.15 GB, 可用容量=93.87 GB, 可移动=false, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=DenvosWindows, 只读=false}
D:\信息:{文件存储类型=NTFS, 总容量=447.13 GB, 可用容量=340.74 GB, 可移动=false, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=SSD_Data, 只读=false}
E:\信息:{文件存储类型=NTFS, 总容量=931.51 GB, 可用容量=455.83 GB, 可移动=false, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=DenvosData, 只读=false}
F:\信息:{文件存储类型=NTFS, 总容量=1.82 TB, 可用容量=809.44 GB, 可移动=false, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=HDD_Data, 只读=false}
G:\信息:{文件存储类型=FAT, 总容量=125.7 MB, 可用容量=115.87 MB, 可移动=true, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=, 只读=false}
H:\信息:{文件存储类型=NTFS, 总容量=29.3 GB, 可用容量=5.59 GB, 可移动=true, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=, 只读=false}
I:\信息:{文件存储类型=NTFS, 总容量=57.73 GB, 可用容量=31.68 GB, 可移动=true, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=KINGSTON, 只读=false}
J:\信息:{文件存储类型=exFAT, 总容量=14.52 GB, 可用容量=7.5 GB, 可移动=true, 是否为CD-ROM=false, 每个扇区大小=512 Bytes, 卷标=Ventoy, 只读=false}

代码分析

实现功能的代码主要在getDiskInfo()方法中。首先通过FileStore fs = Files.getFileStore(Path root);来获取一个FileStore对象,然后通过这个对象来获取磁盘的相应信息的。

上面的代码中创建的fs对象的实现在java.base包中的sun.nio.fs.WindowsFileStore类,而这个类又继承了来自同一个包的抽象类java.nio.file.FileStore类。上面的代码中获取磁盘信息的方法实际上都是使用了被WindowsFileStore类重写的、来自FileSotre类中的方法。

WindowsFileSotre类的实现中,主要使用了java.base包中的sun.nio.fs.WindowsNativeDispatcher类中的方法,而这个类有很多方法都是native方法,即使用了JNI调用了位于%JAVA_HOME%/bin目录中的net.dllnio.dll两个dll中C/C++的方法(JDK文档说nio.dll需要net.dll作为依赖)

例如获取这个磁盘是否可移动的方法fs.getAttribute("volume:isRemovable")实际上调用了nio.dll中的方法Java_sun_nio_fs_WindowsNativeDispatcher_GetDriveType0,相对虚拟地址在00006078

[1] [2]
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇