Чтение файла как потока с использованием полного пути или пути к классам - PullRequest
0 голосов
/ 27 марта 2019

У меня есть метод getMyFilePath(), который может вернуть путь к каталогу как String.

Может возвращать путь к классу: \com\mypackage\configdir\ или же он может вернуть полный путь: C:\configdir\

Я хочу изменить приведенный ниже код, чтобы он мог обрабатывать оба вышеупомянутых случая:

public void myMethod() {
   String myConfigDirPath = getMyFilePath();
   File configFile = new File(myConfigDirPath + "myConfig.txt");
   try (InputStream is = new FileInputStream(configFile)) {
     // do something
   } catch (IOException e) {
      e.printStackTrace();
   }
}

myMethod() работает нормально, когда путь заполнен, т.е. C:\configdir\, но выдает следующую ошибку в строке InputStream, когда путь является classpath, т.е. \com\mypackage\configdir\:

java.io.FileNotFoundException: \com\mypackage\configdir\myConfig.txt 
(The system cannot find the path specified)

Как мне изменить myMethod(), чтобы он работал для обоих типов пути?

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

Вы неправильно используете термин «classpath».Путь к классам - это список каталогов и / или файлов JAR, используемый для разрешения классов и ресурсов во время выполнения или при компиляции.

Правильный термин для \com\mypackage\configdir\myConfig.txt - это ресурс . Можетбыть файлом, пока он находится в вашем исходном дереве, но если вы когда-нибудь попытаетесь упаковать вашу программу в файл jar, он будет находиться внутри архива jar и вообще не будет файлом, поэтому вы не можете прочитать его с помощью FileInputStream.

Ресурс читается с помощью метода getResourceAsStream , который специально предназначен для извлечения статических данных, связанных с приложением:

File configFile = new File(myConfigDirPath + "myConfig.txt");
try (InputStream is = new BufferedInputStream(
    configFile.exists()
        ? new FileInputStream(configFile)
        : MyApplication.class.getResourceAsStream(
            configFile.toString().replace('\\', '/')))) {

    // do something
}

Это можно сделать немного более понятным, переместивваша логика чтения конфигурации для отдельного частного метода:

File configFile = new File(myConfigDirPath + "myConfig.txt");
if (configFile.exists()) {
    try (InputStream is = new BufferedInputStream(
        new FileInputStream(configFile))) {

        readConfigurationFrom(is);
    }
} else {
    String configResourcePath =
        configFile.toString().replace('\\', '/')))) {
    InputStream configResource =
        MyApplication.class.getResourceAsStream(configResourcePath);

    if (configResource == null) {
        throw new ConfigurationException(
            "Cannot find the file \"" + configFile + "\""
            + " or the resource \"" + configResourcePath + "\"");
    }

    try (InputStream is = new BufferedInputStream(configResource)) {
        readConfigurationFrom(is);
    }
}

Некоторые дополнительные примечания:

  • Ресурс указывается в виде относительного URL, например /com/mypackage/configdir/myConfig.txt.URL-адреса всегда используют прямую косую черту (/) на всех платформах.
  • Вы всегда должны читать файл или ресурс, используя BufferedInputStream (или BufferedReader).Это значительно быстрее, чем чтение отдельных байтов непосредственно из файла.
0 голосов
/ 27 марта 2019

Если файл находится в пути к классам, вы можете загрузить файл из пути к классам, используя

      ClassLoader classLoader = <YourClass>.class.getClassLoader();
      InputStream is = classLoader.getResourceAsStream("myConfig.txt");

. Вы можете поместить его в блок Catch или проверить, является ли он путем к классу заранее, а затемпозвоните соответственно

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...