Использует для чтения текстового файла ресурса в String (Java) [закрыто]
215
Есть ли какая-либо утилита, которая помогает читать текстовый файл из ресурса в строку. Я предполагаю, что это популярное требование, но я не смог найти никакой полезности после Google.
@JonSkeet Это замечательно, однако для веб - приложений , это может быть не лучшим решением, реализация getResourceиспользует , Resource.class.getClassLoaderно в веб - приложениях, это может не быть «свой» загрузчик классов, поэтому рекомендуется (например , в [1]) для использования Thread.currentThread().getContextClassLoader().getResourceAsStreamвместо этого (ссылка [1]: stackoverflow.com/questions/676250/… )
Эран Медан
2
@EranMedan: Да, если вы хотите, чтобы контекстный загрузчик классов вы хотели использовать его явно.
Джон Скит
6
В особом случае, когда ресурс находится рядом с вашим классом, вы можете сделать то, Resources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8)что гарантирует использование правильного загрузчика классов.
Богдан Кальмак
2
com.google.common.io.Resourcesотмечен как нестабильный согласно SonarQube
Уклонение от третьей стороны - разумный принцип. К сожалению, основная библиотека, кажется, имеет аллергию на моделирование реальных случаев использования. Посмотрите на Файлы Java 7 и скажите мне, почему чтение всего из ресурса classpath не было там включено? Или, по крайней мере, используя стандартизированную «файловую систему».
Дилум Ранатунга
3
Нужно ли - или нет - необходимо также закрыть поток? Гуава внутренне закрывает поток.
virgo47
Работал красиво для меня тоже! Я также согласен со сторонней вещью: во многих ответах ответом по умолчанию всегда кажется использование какой-либо сторонней библиотеки - будь то от Apache или кого-то еще.
Терье Дал
1
перейти CartApplication.class.getResourceAsStreamна CartApplication.class.getClassLoader().getResourceAsStreamзагрузку ресурсов в текущем jar .. как srm / test / resources
Крис Дамур
5
Хотя я использовал это, я совершенно не согласен избегать сторонних пакетов. Тот факт, что в Java единственный способ легко прочитать файл в строку с помощью трюка со сканером, довольно печален. Альтернатива использованию сторонних библиотек заключается в том, что каждый будет создавать свои собственные оболочки. Guava для ввода-вывода выигрывает, если у вас много потребностей для такого рода операций. Я согласен с тем, что вам не следует импортировать сторонние пакеты, если в вашем коде есть только одно место, где вы хотите это сделать. Это было бы излишним ИМО.
Объясните, пожалуйста, почему это работает, почему это лучше, чем другие альтернативы, и какие соображения производительности / кодирования необходимы.
нанофарад
5
Это nio 2 в Java 1.7. Это родной плод Явы. Для кодирования используйте новую String (bytes, StandardCharsets.UTF_8)
Ковальский Дмитрий
5
в моем случае мне нужно было, getClass().getClassLoader()но в остальном отличное решение!
Эммануэль Тузери
3
Это не сработает, если приложение упаковано в банку.
Даниэль Бо
65
Чистое и простое, дружественное к банкам решение Java 8+
Этот простой метод, приведенный ниже, отлично подойдет, если вы используете Java 8 или выше:
/**
* Reads given resource file as a string.
*
* @param fileName path to the resource file
* @return the file's contents
* @throws IOException if read fails for any reason
*/staticString getResourceFileAsString(String fileName)throwsIOException{ClassLoader classLoader =ClassLoader.getSystemClassLoader();try(InputStream is = classLoader.getResourceAsStream(fileName)){if(is ==null)returnnull;try(InputStreamReader isr =newInputStreamReader(is);BufferedReader reader =newBufferedReader(isr)){return reader.lines().collect(Collectors.joining(System.lineSeparator()));}}}
И это также работает с ресурсами в jar-файлах .
О кодировке текста: InputStreamReaderбудет использоваться системная кодировка по умолчанию, если вы ее не указали. Вы можете указать это самостоятельно, чтобы избежать проблем с декодированием, например:
newInputStreamReader(isr,StandardCharsets.UTF_8);
Избегайте ненужных зависимостей
Всегда предпочитайте не зависеть от больших, толстых библиотек. Если вы уже не используете Guava или Apache Commons IO для других задач, добавление этих библиотек в ваш проект просто для возможности чтения из файла кажется слишком сложным.
«Простой» метод? Ты, должно быть, Прикалываешься
Я понимаю, что чистая Java не делает хорошую работу, когда дело доходит до выполнения простых задач, подобных этой. Например, вот как мы читаем из файла в Node.js:
Простой и легкий для чтения (хотя людям все равно нравится полагаться на многие зависимости, в основном из-за невежества). Или в Python:
with open('some-file.txt','r')as f:
content = f.read()
Это печально, но все еще просто для стандартов Java, и все, что вам нужно сделать, это скопировать метод выше в свой проект и использовать его. Я даже не прошу вас понять, что там происходит, потому что это действительно ни для кого не имеет значения. Это просто работает, точка :-)
@zakmck, пожалуйста, постарайтесь, чтобы ваши комментарии были конструктивными. Когда вы становитесь зрелым разработчиком, вы узнаете, что иногда вы действительно хотите «заново изобрести колесо». Например, вам может потребоваться, чтобы ваш бинарный файл был ниже порогового размера. Библиотеки часто увеличивают размер вашего приложения на несколько порядков. Можно было бы возразить прямо противоположное тому, что вы сказали: «Не нужно писать код. Да, давайте просто каждый раз импортировать библиотеки». Вы бы действительно предпочли импортировать библиотеку, чтобы сохранить 3 строки кода? Могу поспорить, что добавление библиотеки увеличит ваш LOC более чем на это. Ключ баланс.
Лусио Пайва
3
Ну, не каждый работает в облаке. Например, везде есть встроенные системы, работающие на Java. Я просто не вижу смысла в том, чтобы критиковать ответы, которые обеспечивают абсолютно правильные подходы, учитывая, что вы упомянули себя, что примете предложение использовать JDK непосредственно в своем собственном коде. В любом случае, давайте постараемся сохранять комментарии строго, чтобы помочь улучшить ответы, а не обсуждать мнения.
Лучио Пайва
1
Хорошее решение только для JDK. Я хотел бы только добавить проверку , если InputStreamпеременная isявляется nullили нет.
scrutari
2
Ницца. Я использовал это. Вы можете рассмотреть закрытие потоков / читателей тоже.
димплекс
1
@RobertBain Я отредактировал ответ, чтобы добавить информацию о предупреждении кодировки. Дайте мне знать, если вы узнаете, что пошло не так с загрузчиком классов в AWS, чтобы я мог добавить это и к ответу. Спасибо!
Лусио Пайва
57
В Guava есть метод toString для чтения файла в строку:
Или, если это входной поток, у гуавы есть хороший способ для этогоString stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
Я предпочитаю "" этому в этом случае это недоступно
user833970
11
Подобно тому , как компактный, но при надлежащем закрытии входного потока: IOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8").
Богдан Кальмак
1
Если это решение не работает, попробуйте добавить getClassLoader()в метод цепи: String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
URL url =Resources.getResource("myFile.txt");File myFile =newFile(url.toURI());String content =FileUtils.readFileToString(myFile,"UTF-8");// or any other encoding
Почему нужно указывать кодировку, я не понимаю. Если я читаю файл, я просто хочу узнать, что в нем, он должен выяснить, в какой кодировке он работает, как в моем редакторе. Когда я открываю в Notepad или ++, я не говорю ему, какую кодировку он должен использовать. Я использую этот метод, а затем writeStringToFile ... но содержание отличается. Я получаю странные токены в клонированном файле ... я не понимаю, почему мне нужно указать кодировку.
ммм
11
@Hamidan, выбор правильной кодировки - очень сложный алгоритм. Это часто реализуется в текстовом редакторе, но иногда они не могут определить правильную кодировку. Я не ожидал бы, что API чтения файлов внедрит такой сложный алгоритм для чтения моего файла.
Винсент Роберт
1
@SecretService Кроме того, эти алгоритмы используют информацию, такую как язык операционной системы, языковой стандарт и другие региональные настройки, что означает, что чтение файла без указания кодировки может работать в ваших настройках, но не в чьих-либо других.
Я не думаю, что это сработает, если ресурс будет найден внутри банки. Тогда это не будет файл.
Вилле Ойкаринен
16
У меня часто была эта проблема сама. Чтобы избежать зависимости от небольших проектов, я часто пишу небольшую служебную функцию, когда мне не нужны обычные и т. Д. Вот код для загрузки содержимого файла в строковый буфер:
StringBuffer sb =newStringBuffer();BufferedReader br =newBufferedReader(newInputStreamReader(getClass().getResourceAsStream("path/to/textfile.txt"),"UTF-8"));for(int c = br.read(); c !=-1; c = br.read()) sb.append((char)c);System.out.println(sb.toString());
Указание кодировки является важным в этом случае, потому что вы , возможно , редактировали файл в кодировке UTF-8, а затем поместить его в банку, и компьютер , который открывает файл может иметь CP-1251 в его родной кодировке файла (например) ; так что в этом случае вы никогда не знаете целевую кодировку, поэтому информация о явном кодировании имеет решающее значение. Кроме того, цикл чтения файла char по char кажется неэффективным, но он используется в BufferedReader и, таким образом, на самом деле довольно быстро.
Файл работает только для ресурсов classpath, которые, ну, в общем, файлы. Нет, если они являются элементами в файле .jar или частью толстого фляги, одной из других реализаций загрузчика классов.
toolforger
2
Я использую следующее для чтения файлов ресурсов из classpath:
package test;import java.io.InputStream;import java.nio.charset.StandardCharsets;import java.util.Scanner;publicclassMain{publicstaticvoid main(String[] args){try{String fileContent = getFileFromResources("resourcesFile.txt");System.out.println(fileContent);}catch(Exception e){
e.printStackTrace();}}//USE THIS FUNCTION TO READ CONTENT OF A FILE, IT MUST EXIST IN "RESOURCES" FOLDERpublicstaticString getFileFromResources(String fileName)throwsException{ClassLoader classLoader =Main.class.getClassLoader();InputStream stream = classLoader.getResourceAsStream(fileName);String text =null;try(Scanner scanner =newScanner(stream,StandardCharsets.UTF_8.name())){
text = scanner.useDelimiter("\\A").next();}return text;}}
По крайней мере, начиная с Apache commons-io 2.5, метод IOUtils.toString () поддерживает аргумент URI и возвращает содержимое файлов, расположенных внутри jar-файлов в classpath:
Мне нравится ответ Акосицки с помощью глупого трюка со сканером. Это самое простое из всех, что я вижу, без внешних зависимостей, которое работает в Java 8 (и фактически вплоть до Java 5). Вот еще более простой ответ, если вы можете использовать Java 9 или выше (так как InputStream.readAllBytes()был добавлен в Java 9):
String text =newString(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());
Пожалуйста, обратитесь сюда, чтобы сравнить 3 способа (по BufferedReaderсравнению с Гуавой Filesи Гуавой Resources), чтобы получить Stringиз текстового файла.
Откуда берутся IOUtils? На источник следует ссылаться четко.
ehecatl
0
Я написал здесь методы readResource () , чтобы сделать это одним простым вызовом. Это зависит от библиотеки Guava, но мне нравятся методы только для JDK, предложенные в других ответах, и я думаю, что я изменю их таким образом.
publicclassUtils{publicstaticString readResource(String name)throwsURISyntaxException,IOException{
var uri =Utils.class.getResource("/"+ name).toURI();
var path =Paths.get(uri);returnFiles.readString(path);}}
Мне нравятся утилиты Apache commons для такого типа вещей, и я очень часто использую этот точный вариант использования (чтение файлов из classpath) при тестировании, особенно для чтения файлов JSON /src/test/resourcesв рамках модульного / интеграционного тестирования. например
publicclassFileUtils{publicstaticString getResource(String classpathLocation){try{String message =IOUtils.toString(FileUtils.class.getResourceAsStream(classpathLocation),Charset.defaultCharset());return message;}catch(IOException e){thrownewRuntimeException("Could not read file [ "+ classpathLocation +" ] from classpath", e);}}}
В целях тестирования может быть неплохо поймать IOExceptionи выбросить RuntimeException- ваш тестовый класс может выглядеть так:
@Testpublicvoid shouldDoSomething (){String json =FileUtils.getResource("/json/input.json");// Use json as part of test ...}
Ответы:
Да, Гуава предоставляет это в
Resources
классе. Например:источник
getResource
использует ,Resource.class.getClassLoader
но в веб - приложениях, это может не быть «свой» загрузчик классов, поэтому рекомендуется (например , в [1]) для использованияThread.currentThread().getContextClassLoader().getResourceAsStream
вместо этого (ссылка [1]: stackoverflow.com/questions/676250/… )Resources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8)
что гарантирует использование правильного загрузчика классов.com.google.common.io.Resources
отмечен как нестабильный согласно SonarQubeguava
изменил реализацию. Для гуавы 23 реализация нравится следующее.ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
Вы можете использовать старый трюк Oneliner для Stupid Scanner, чтобы сделать это без каких-либо дополнительных зависимостей, таких как guava:
Ребята, не используйте сторонние материалы, если вам это действительно не нужно. В JDK уже много функциональности.
источник
CartApplication.class.getResourceAsStream
наCartApplication.class.getClassLoader().getResourceAsStream
загрузку ресурсов в текущем jar .. как srm / test / resourcesДля Java 7:
источник
getClass().getClassLoader()
но в остальном отличное решение!Чистое и простое, дружественное к банкам решение Java 8+
Этот простой метод, приведенный ниже, отлично подойдет, если вы используете Java 8 или выше:
И это также работает с ресурсами в jar-файлах .
О кодировке текста:
InputStreamReader
будет использоваться системная кодировка по умолчанию, если вы ее не указали. Вы можете указать это самостоятельно, чтобы избежать проблем с декодированием, например:Избегайте ненужных зависимостей
Всегда предпочитайте не зависеть от больших, толстых библиотек. Если вы уже не используете Guava или Apache Commons IO для других задач, добавление этих библиотек в ваш проект просто для возможности чтения из файла кажется слишком сложным.
«Простой» метод? Ты, должно быть, Прикалываешься
Я понимаю, что чистая Java не делает хорошую работу, когда дело доходит до выполнения простых задач, подобных этой. Например, вот как мы читаем из файла в Node.js:
Простой и легкий для чтения (хотя людям все равно нравится полагаться на многие зависимости, в основном из-за невежества). Или в Python:
Это печально, но все еще просто для стандартов Java, и все, что вам нужно сделать, это скопировать метод выше в свой проект и использовать его. Я даже не прошу вас понять, что там происходит, потому что это действительно ни для кого не имеет значения. Это просто работает, точка :-)
источник
InputStream
переменнаяis
являетсяnull
или нет.В Guava есть метод toString для чтения файла в строку:
Этот метод не требует, чтобы файл был в пути к классам (как в предыдущем ответе Джона Скита ).
источник
String stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
yegor256 нашел хорошее решение, используя Apache Commons IO :
источник
IOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8")
.getClassLoader()
в метод цепи:String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
У apache-commons-io есть имя утилиты
FileUtils
:источник
У меня часто была эта проблема сама. Чтобы избежать зависимости от небольших проектов, я часто пишу небольшую служебную функцию, когда мне не нужны обычные и т. Д. Вот код для загрузки содержимого файла в строковый буфер:
Указание кодировки является важным в этом случае, потому что вы , возможно , редактировали файл в кодировке UTF-8, а затем поместить его в банку, и компьютер , который открывает файл может иметь CP-1251 в его родной кодировке файла (например) ; так что в этом случае вы никогда не знаете целевую кодировку, поэтому информация о явном кодировании имеет решающее значение. Кроме того, цикл чтения файла char по char кажется неэффективным, но он используется в BufferedReader и, таким образом, на самом деле довольно быстро.
источник
Вы можете использовать следующий код формы Java
источник
Если вы хотите получить вашу String из ресурса проекта, такого как файл testcase / foo.json в src / main / resources вашего проекта, сделайте это:
Обратите внимание, что метод getClassLoader () отсутствует в некоторых других примерах.
источник
Используйте Apache FileUtils. У него есть метод readFileToString
источник
Я использую следующее для чтения файлов ресурсов из
classpath
:Никаких сторонних зависимостей не требуется.
источник
С набором статического импорта решение Guava может быть очень компактным:
Требуется следующий импорт:
источник
источник
По крайней мере, начиная с Apache commons-io 2.5, метод IOUtils.toString () поддерживает аргумент URI и возвращает содержимое файлов, расположенных внутри jar-файлов в classpath:
источник
Мне нравится ответ Акосицки с помощью глупого трюка со сканером. Это самое простое из всех, что я вижу, без внешних зависимостей, которое работает в Java 8 (и фактически вплоть до Java 5). Вот еще более простой ответ, если вы можете использовать Java 9 или выше (так как
InputStream.readAllBytes()
был добавлен в Java 9):источник
Guava также имеет,
Files.readLines()
если вы хотите, чтобы возвращаемое значение былоList<String>
построчно:Пожалуйста, обратитесь сюда, чтобы сравнить 3 способа (по
BufferedReader
сравнению с ГуавойFiles
и ГуавойResources
), чтобы получитьString
из текстового файла.источник
Charsets
также в Гуаве. Смотрите это: google.github.io/guava/releases/23.0/api/docsВот мой подход работал нормально
источник
Я написал здесь методы readResource () , чтобы сделать это одним простым вызовом. Это зависит от библиотеки Guava, но мне нравятся методы только для JDK, предложенные в других ответах, и я думаю, что я изменю их таким образом.
источник
Если вы включите Guava, то вы можете использовать:
(Другие решения упоминали другой метод для Guava, но они устарели)
источник
У меня работают следующие трески:
источник
Вот решение с использованием Java 11
Files.readString
:источник
Я сделал статический метод NO-зависимости следующим образом:
источник
Мне нравятся утилиты Apache commons для такого типа вещей, и я очень часто использую этот точный вариант использования (чтение файлов из classpath) при тестировании, особенно для чтения файлов JSON
/src/test/resources
в рамках модульного / интеграционного тестирования. напримерВ целях тестирования может быть неплохо поймать
IOException
и выброситьRuntimeException
- ваш тестовый класс может выглядеть так:источник
источник