I'm trying to have my Java application read all the data in a given path. So files, directories, metadata etc. This also includes one weird thing NTFS has called Alternate Data Stream (ADS).
Apparently it's like a second layer of data in a directory or file. You can open the command prompt and create a file in the ADS using ':', for example:
C:\ADSTest> echo test>:ads.txt
So,
C:\ADSTest> notepad :ads.txt
Should open a notepad that contains the string "test" in it. However, if you did:
C:\ADSTest> dir
You will not be able to see ads.txt. However, if you use the dir option that displays ADS data, you will be able to see it:
C:\ADSTest> dir /r
MM/dd/yyyy hh:mm .:ads.txt
Now, I am aware that Java IO has the capability to read ADS. How do I know that? Well, Oracle's documentations clearly states so:
If the file attributes supported by your file system implementation aren't sufficient for your needs, you can use the UserDefinedAttributeView to create and track your own file attributes.
Some implementations map this concept to features like NTFS Alternative Data Streams and extended attributes on file systems such as ext3 and ZFS.
Also, a random post on a random forum :D
The data is stored in NTFS Alternate data streams (ADS) which are readable through Java IO (I have tested it).
The problem is, I can't find any pre-written file attribute viewer that can parse ADS, and I don't understand how to write an ADS parser of my own. I'm a beginner programmer so I feel this is way over my head. Would anybody please help me out or point me in the right direction?
Solution
EDIT: With the help of @knosrtum I was able to concoct a method that will return all the parsed ADS information from a given path as an ArrayList of Strings (it can also be easily edited to an ArrayList of files). Here's the code for anyone who might need it:
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;
}
}
I was able to read the ADS of a file simply by opening the the file with the syntax "file_name:stream_name". So if you've done this:
Then you should be able to do this:
If you want to get the ADS data from the
dir /r
command, I think you just need to execute a shell and capture the output:Now you can use the first code listing to print the ADS data.