2

我正在为我们的应用程序开发一个图形安装程序。由于没有可用的安装程序生成器满足要求和约束,我正在从头开始构建它。

安装程序应该在多个操作系统上运行,因此路径处理需要与操作系统无关。为此,我编写了以下小实用程序:

public class Path {
  private Path() {
  }

  public static String join(String... pathElements) {
    return ListEnhancer.wrap(Arrays.asList(pathElements)).
      mkString(File.separator);
  }

  public static String concatOsSpecific(String path, String element) {
    return path + File.separator + element;
  }

  public static String concatOsAgnostic(String path, String element) {
    return path + "/" + element;
  }

  public static String makeOsAgnostic(String path) {
    return path.replace(File.separator, "/");
  }

  public static String makeOsSpecific(String path) {
    return new File(path).getAbsolutePath();
  }

  public static String fileName(String path) {
    return new File(path).getName();
  }
}

现在我的代码到处都是,Path.*Agnostic并且Path.*Specific在很多地方调用。很明显,这很容易出错并且根本不透明。

我应该采取什么方法来使路径处理透明且不易出错?是否存在已经解决此问题的任何实用程序/库?任何帮助将不胜感激。

编辑:

为了举例说明我的意思,这是我不久前写的一些代码。(题外话:原谅冗长的方法。代码处于初始阶段,很快将进行一些重度重构。)

一些上下文:ApplicationContext是一个存储安装数据的对象。installationRootDirectory其中包括多个路径,例如installationDirectory等。这些路径的默认值是在创建安装程序时指定的,因此始终以与操作系统无关的格式存储。

@Override
protected void initializeComponents() {
  super.initializeComponents();
  choosePathLabel = new JLabel("Please select the installation path:");
  final ApplicationContext c = installer.getAppContext();
  pathTextField = new JTextField(
    Path.makeOsSpecific(c.getInstallationDirectory()));
  browseButton = new JButton("Browse", 
    new ImageIcon("resources/images/browse.png"));
  browseButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
      JFileChooser fileChooser = new JFileChooser();
      fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      fileChooser.setAcceptAllFileFilterUsed(false);
      int choice = fileChooser.showOpenDialog(installer);
      String selectedInstallationRootDir = fileChooser.getSelectedFile().
        getPath();
      if (choice == JFileChooser.APPROVE_OPTION) {
        c.setInstallationRootDirectory(
          Path.makeOsAgnostic(selectedInstallationRootDir));
        pathTextField.setText(Path.makeOsSpecific(c.getInstallationDirectory()));
      }
    }
  });
}
4

4 回答 4

4

或者您可以引入 2 个新课程:

class OsSpecificPath implements FilePathInterface
{
      String path;

      OsAgnosticPath toAgnosticPath();

      OsSpecificPath concat( OsSpecificPath otherPath );

      // from IFilePath
      getFile();

     ... etc
}

class OsAgnosticPath implements FilePathInterface
{
      String path;

      OsSpecificPath toOsSpecificPath();

      OsAgnosticPath concat( OsAgnosticPath otherPath );

      // from IFilePath
      getFile();

     ... etc
}

每个人都绕着他们需要的路径。

然后,每个方法都可以具有转换为其他类型路径的方法,但不是所有内容都是字符串并且可能被滥用的“字符串类型”解决方案,而是有 2 个不能错误传递的强类型类大约。

任何不关心路径类型的东西都会使用FilePathInterface,任何需要对特定类型的路径进行操作的东西都会专门使用这些类型。 如果真的有必要,FilePathInterface可以假设在界面中同时具有toAgnosticPath和...toOsSpecificPath

于 2012-05-31T20:42:06.057 回答
1

不确定这是否是您想要的,但通常当我需要在独立于操作系统的 Java 程序中执行与路径相关的操作时,我总是使用字符串而不是文件来传递路径,并且我总是执行以下两个操作事物:

每当我构建字符串路径时,我总是将/其用作文件分隔符

每当我使用字符串路径创建文件或将其另存为文本时,我总是在使用路径之前进行以下调用:

String fSep = System.getProperty("file.separator);
String path = ... //might be built from scratch, might be passed in from somewhere
path = path.replace("/",fSep).replace("\\",fSep);

无论路径是在本地计算机上构建还是从具有不同操作系统的网络上的另一台计算机传入,这似乎都能正常工作,前提是我打算使用本地计算机上的路径。如果您计划通过网络在不同操作系统之间传递路径,请注意您自己的代码是一致的。

编辑

哇...不知何故,我的答案被弄乱了,代码格式没有按最初的预期工作...

于 2012-05-31T20:16:55.197 回答
0

我会制作我自己的 MyFile 对象来扩展或包装 java.util.File。然后确保所有代码都使用这个对象而不是 java.io.File。在这里,您将进行操作系统检查并调用方法来清理文件名。您的其余代码将是“干净的”。

于 2012-05-31T20:20:34.307 回答
0

您永远不需要转换os-agnostic。以下是特定于操作系统的转换:

public class Path {
  private Path() {
  }

  public static String concat(String path, String element) {
    return new File(path, element).getPath();
  }

  public static String makeOsSpecific(String path) {
    return new File(path).getAbsolutePath();
  }

  public static String fileName(String path) {
    return new File(path).getName();
  }
}

您的样品:

@Override
protected void initializeComponents() {
  super.initializeComponents();
  choosePathLabel = new JLabel("Please select the installation path:");
  final ApplicationContext c = installer.getAppContext();
  pathTextField = new JTextField(
    Path.makeOsSpecific(c.getInstallationDirectory()));
  browseButton = new JButton("Browse", 
    new ImageIcon("resources/images/browse.png"));
  browseButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
      JFileChooser fileChooser = new JFileChooser();
      fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      fileChooser.setAcceptAllFileFilterUsed(false);
      int choice = fileChooser.showOpenDialog(installer);
      String selectedInstallationRootDir = fileChooser.getSelectedFile().
        getPath();
      if (choice == JFileChooser.APPROVE_OPTION) {
        c.setInstallationRootDirectory(selectedInstallationRootDir);
        pathTextField.setText(Path.makeOsSpecific(c.getInstallationDirectory()));
      }
    }
  });
}
于 2012-06-01T00:42:26.093 回答