Selecting 'Computer' or 'Libraries'

2019-07-21 03:34发布

问题:

I'm using JFileChooser in a very standard "Save As" situation. A am generating a file, and the user is picking where to save it.

Confusingly, the user can pick number of "not real" folders. In Windows 7 they are: Computer, Network, Libraries, Homegroup. When I invoke chooser.getSelectedFile(); I get a file object, but it is very odd. It makes sense that this would be a strange File object since it doesn't correspond to a file which could actually exist. If I try to use the file, for example calling getCanonicalPath, I get an IOException. But what doesn't make sense, as a programmer, is my lack of information about this File object or its parent.

I would like to configure the JFileChooser so that it doesn't permit the user to make such a selection. Thus far I've found that using this works:

setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

However the user is then picking the directory of the new file but not the name.

Alternately, I would like to at least explain why they can't save in that location. All my attempts to get the name, e.g. "Computer," "Network," or "Libraries" have failed. Using Java 6 on Windows 7, FileSystemView methods like isComputerNode and isFileSystem, which should address this question, don't help.

import java.awt.Component;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileSystemView;

public class JChooserTest {

public static void main(String[] args) {

    JFileChooser chooser = new JFileChooser();
    chooser.setSelectedFile(new File("C:/foo.txt"));
    chooser.setDialogTitle("Save As");
    chooser.setFileHidingEnabled(true);
    chooser.setMultiSelectionEnabled(false);
    chooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_AND_DIRECTORIES);
    chooser.setDialogType(JFileChooser.SAVE_DIALOG);
    Component parentComponent = null; // is not null in the real world 
    int state=chooser.showDialog(parentComponent, "Save As");
    if (state == JFileChooser.CANCEL_OPTION) return;

    File dest = chooser.getSelectedFile();

    try {
        System.out.println("Valid Destination: " + dest.getCanonicalPath());

    } catch (IOException ex) { // getCanonicalPath() threw IOException

        File parent = dest.getParentFile();

        FileSystemView fsv = FileSystemView.getFileSystemView();

        //log.error("Error determining the CanonicalPath of " + dest, ex);
        System.out.println("dest.getName: " + dest.getName());
        System.out.println("parent.getName: " + parent.getName());          
        System.out.println("getSystemDisplayName of dest: " + fsv.getSystemDisplayName(dest));
        System.out.println("getSystemDisplayName of parent: " + fsv.getSystemDisplayName(parent));          
        System.out.println("getSystemTypeDescription of dest: " + fsv.getSystemTypeDescription(dest));
        System.out.println("getSystemTypeDescription of parent: " + fsv.getSystemTypeDescription(parent));
        System.out.println("isFileSystem of dest: " + fsv.isFileSystem(dest));
        System.out.println("isFileSystem of parent: " + fsv.isFileSystem(parent));
        System.out.println("isComputerNode of dest: " + fsv.isComputerNode(dest));
        System.out.println("isComputerNode of parent: " + fsv.isComputerNode(parent));          
        System.out.println("dest" + dest.isDirectory());
        System.out.println("parent" + parent.isDirectory());
    }
}

}

回答1:

The returned File object has a name of ::{031E4825-7B94-4DC3-B131-E946B44C8DD5}. Unfortunately, this is actually the name of the libraries folder, and it exists only in Explorer's imagination, not to anyone else.

For example, create a folder somewhere (for example, on your desktop), called foo.{031E4825-7B94-4DC3-B131-E946B44C8DD5}, and open it. Explorer will think it's the Libraries folder, but everything else will be awfully confused:

 Directory of C:\Users\Faux\Desktop\lol.{031E4825-7B94-4DC3-B131-E946B44C8DD5}

17/02/2012  08:06 pm    <DIR>          .
17/02/2012  08:06 pm    <DIR>          ..
               0 File(s)              0 bytes
               2 Dir(s)  794,214,469,632 bytes free

As to how to convince file chooser to not show them, I have no idea. I'd suggest trying getCanonicalPath(), catching the exception (as you are) and returning it to the user; suggesting they pick somewhere else.