【问题标题】:How do I read Windows NTFS's Alternate Data Stream using Java's IO?如何使用 Java IO 读取 Windows NTFS 备用数据流?
【发布时间】:2015-10-12 15:50:41
【问题描述】:

我正在尝试让我的 Java 应用程序读取给定路径中的所有数据。所以文件、目录、元数据等。这还包括 NTFS 称为备用数据流 (ADS) 的一种奇怪的东西。

显然它就像目录或文件中的第二层数据。您可以打开命令提示符并使用“:”在 ADS 中创建文件,例如:

C:\ADSTest> echo test>:ads.txt

所以,

C:\ADSTest> notepad :ads.txt

应该打开一个包含字符串“test”的记事本。但是,如果你这样做了:

C:\ADSTest> dir

您将看不到 ads.txt。但是,如果您使用显示 ADS 数据的 dir 选项,您将能够看到它:

C:\ADSTest> dir /r
MM/dd/yyyy hh:mm            .:ads.txt

现在,我知道 Java IO 具有读取 ADS 的能力。我怎么知道?嗯,Oracle's documentations clearly states so

如果您的文件系统实现支持的文件属性 不足以满足您的需求,您可以使用 UserDefinedAttributeView 来创建和跟踪您自己的文件属性。

一些实现将此概念映射到 NTFS 等功能 文件系统上的替代数据流和扩展属性,例如 作为 ext3 和 ZFS。

另外,a random post on a random forum :D

数据存储在 NTFS 备用数据流 (ADS) 中 通过 Java IO 可读(我已经测试过了)。

问题是,我找不到任何可以解析 ADS 的预先编写的文件属性查看器,而且我不明白如何编写自己的 ADS 解析器。我是一个初学者程序员,所以我觉得这太过分了。有人可以帮助我或指出正确的方向吗?

解决方案

编辑: 在@knosrtum 的帮助下,我能够设计一种方法,该方法将从给定路径返回所有已解析的 ADS 信息作为字符串的 ArrayList(它也可以轻松编辑为一个文件的 ArrayList)。这是任何可能需要它的人的代码:

public class ADSReader {

    public static ArrayList<String> start(Path toParse) {

        String path = toParse.toString();
        ArrayList<String> parsedADS = new ArrayList<>();

        final String command = "cmd.exe /c dir " + path + " /r"; // listing of given Path.

        final Pattern pattern = Pattern.compile(
                "\\s*"                 // any amount of whitespace
                        + "[0123456789,]+\\s*"   // digits (with possible comma), whitespace
                        + "([^:]+:"    // group 1 = file name, then colon,
                        + "[^:]+:"     // then ADS, then colon,
                        + ".+)");      // then everything else.

        try {
            Process process = Runtime.getRuntime().exec(command);
            process.waitFor();
            try (BufferedReader br = new BufferedReader(
                    new InputStreamReader(process.getInputStream()))) {
                String line;

                while ((line = br.readLine()) != null) {
                    Matcher matcher = pattern.matcher(line);
                    if (matcher.matches()) {
                        parsedADS.add((matcher.group(1)));
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        for (int z = 0; z<parsedADS.size(); z++)
            System.out.println(parsedADS.get(z));

        return parsedADS;

    }
}

【问题讨论】:

    标签: java io java-io ntfs alternate-data-stream


    【解决方案1】:

    我可以通过使用语法“file_name:stream_name”打开文件来读取文件的 ADS。所以如果你这样做了:

    C:>echo Hidden text > test.txt:hidden
    

    那么你应该可以做到这一点:

    package net.snortum.play;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class AdsPlay {
        public static void main(String[] args) {
            new AdsPlay().start();
        }
    
        private void start() {
            File file = new File("test.txt:hidden");
            try (BufferedReader bf = new BufferedReader( new FileReader(file))) {
                String hidden = bf.readLine();
                System.out.println(hidden);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    如果你想从dir /r命令中获取ADS数据,我想你只需要执行一个shell并捕获输出:

    package net.snortum.play;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class ExecPlay {
    
        public static void main(String[] args) {
            new ExecPlay().start();
        }
    
        private void start() {
            String fileName = "not found";
            String ads = "not found";
            final String command = "cmd.exe /c dir /r"; // listing of current directory
    
            final Pattern pattern = Pattern.compile(
                      "\\s*"                 // any amount of whitespace
                    + "[0123456789,]+\\s*"   // digits (with possible comma), whitespace
                    + "([^:]+):"             // group 1 = file name, then colon
                    + "([^:]+):"             // group 2 = ADS, then colon
                    + ".+");                 // everything else
    
            try {
                Process process = Runtime.getRuntime().exec(command);
                process.waitFor();
                try (BufferedReader br = new BufferedReader(
                        new InputStreamReader(process.getInputStream()))) {
                    String line;
    
                    while ((line = br.readLine()) != null) {
                        Matcher matcher = pattern.matcher(line);
                        if (matcher.matches()) {
                            fileName = matcher.group(1);
                            ads = matcher.group(2);
                            break;
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println(fileName + ", " + ads);
    
        }
    }
    

    现在您可以使用第一个代码清单来打印 ADS 数据。

    【讨论】:

    • 酷!但是,正如我在原始帖子中所述,我需要此功能来读取给定路径中的所有数据。如果你运行dir /r,可以把它想象成Windows DIR 命令。通常,我会使用DirectoryStream&lt;Path&gt; stream = Files.newDirectoryStream(localDir),但这不会读取 ADS。所以我需要能够检测文件流中的 ADS 数据并将其放置在路径的 ArrayList 中。我将如何修改此代码以适应这种情况?
    • 感谢您的编辑,但有没有办法将其转换为返回 特别是 ADS 路径的 ArrayList 或 ADS 的 Path 类对象的方法路径(理想情况下只使用 Java IO 实现),所以我可以将它插入到我的应用程序的 ArrayList 中,该路径已经包含要传递给我的过滤和排序方法的所有正常解析的路径?
    • 如果您确切知道 ADS 名称,您可以使用 NIO 编写代码来读取或测试它。在上面的示例中,ADS 名称将是“隐藏的”。但是,如果您不知道确切的名称,我不知道有一种 Java IO 方法来判断文件上是否有 any ADS 信息。我认为你必须使用我上面写的dir /r 解析器。
    • 我已经设法通过稍微调整您的代码来设计一种方法来满足我的需求。非常感谢,我学到了很多新东西!
    猜你喜欢
    • 2010-12-21
    • 2014-12-13
    • 2013-10-18
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-10
    • 1970-01-01
    相关资源
    最近更新 更多