Есть ли какая-либо утилита, которая помогает читать текстовый файл из ресурса в строку. Я предполагаю, что это популярное требование, но я не смог найти никакой полезности после Google.
Есть ли какая-либо утилита, которая помогает читать текстовый файл из ресурса в строку. Я предполагаю, что это популярное требование, но я не смог найти никакой полезности после Google.
Ответы:
Да, Гуава предоставляет это в Resources
классе. Например:
URL url = Resources.getResource("foo.txt");
String text = Resources.toString(url, StandardCharsets.UTF_8);
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
отмечен как нестабильный согласно SonarQube
guava
изменил реализацию. Для гуавы 23 реализация нравится следующее. ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
Вы можете использовать старый трюк Oneliner для Stupid Scanner, чтобы сделать это без каких-либо дополнительных зависимостей, таких как guava:
String text = new Scanner(AppropriateClass.class.getResourceAsStream("foo.txt"), "UTF-8").useDelimiter("\\A").next();
Ребята, не используйте сторонние материалы, если вам это действительно не нужно. В JDK уже много функциональности.
CartApplication.class.getResourceAsStream
на CartApplication.class.getClassLoader().getResourceAsStream
загрузку ресурсов в текущем jar .. как srm / test / resources
Для Java 7:
new String(Files.readAllBytes(Paths.get(getClass().getResource("foo.txt").toURI())));
getClass().getClassLoader()
но в остальном отличное решение!
Этот простой метод, приведенный ниже, отлично подойдет, если вы используете 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
*/
static String getResourceFileAsString(String fileName) throws IOException {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try (InputStream is = classLoader.getResourceAsStream(fileName)) {
if (is == null) return null;
try (InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr)) {
return reader.lines().collect(Collectors.joining(System.lineSeparator()));
}
}
}
И это также работает с ресурсами в jar-файлах .
О кодировке текста: InputStreamReader
будет использоваться системная кодировка по умолчанию, если вы ее не указали. Вы можете указать это самостоятельно, чтобы избежать проблем с декодированием, например:
new InputStreamReader(isr, StandardCharsets.UTF_8);
Всегда предпочитайте не зависеть от больших, толстых библиотек. Если вы уже не используете Guava или Apache Commons IO для других задач, добавление этих библиотек в ваш проект просто для возможности чтения из файла кажется слишком сложным.
Я понимаю, что чистая Java не делает хорошую работу, когда дело доходит до выполнения простых задач, подобных этой. Например, вот как мы читаем из файла в Node.js:
const fs = require("fs");
const contents = fs.readFileSync("some-file.txt", "utf-8");
Простой и легкий для чтения (хотя людям все равно нравится полагаться на многие зависимости, в основном из-за невежества). Или в Python:
with open('some-file.txt', 'r') as f:
content = f.read()
Это печально, но все еще просто для стандартов Java, и все, что вам нужно сделать, это скопировать метод выше в свой проект и использовать его. Я даже не прошу вас понять, что там происходит, потому что это действительно ни для кого не имеет значения. Это просто работает, точка :-)
InputStream
переменная is
является null
или нет.
В Guava есть метод toString для чтения файла в строку:
import com.google.common.base.Charsets;
import com.google.common.io.Files;
String content = Files.toString(new File("/home/x1/text.log"), Charsets.UTF_8);
Этот метод не требует, чтобы файл был в пути к классам (как в предыдущем ответе Джона Скита ).
String stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
yegor256 нашел хорошее решение, используя Apache Commons IO :
import org.apache.commons.io.IOUtils;
String text = IOUtils.toString(this.getClass().getResourceAsStream("foo.xml"),
"UTF-8");
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
:
URL url = Resources.getResource("myFile.txt");
File myFile = new File(url.toURI());
String content = FileUtils.readFileToString(myFile, "UTF-8"); // or any other encoding
У меня часто была эта проблема сама. Чтобы избежать зависимости от небольших проектов, я часто пишу небольшую служебную функцию, когда мне не нужны обычные и т. Д. Вот код для загрузки содержимого файла в строковый буфер:
StringBuffer sb = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(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 и, таким образом, на самом деле довольно быстро.
Вы можете использовать следующий код формы Java
new String(Files.readAllBytes(Paths.get(getClass().getResource("example.txt").toURI())));
Если вы хотите получить вашу String из ресурса проекта, такого как файл testcase / foo.json в src / main / resources вашего проекта, сделайте это:
String myString=
new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("testcase/foo.json").toURI())));
Обратите внимание, что метод getClassLoader () отсутствует в некоторых других примерах.
Используйте Apache FileUtils. У него есть метод readFileToString
Я использую следующее для чтения файлов ресурсов из classpath
:
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.Scanner;
public class ResourceUtilities
{
public static String resourceToString(String filePath) throws IOException, URISyntaxException
{
try (InputStream inputStream = ResourceUtilities.class.getClassLoader().getResourceAsStream(filePath))
{
return inputStreamToString(inputStream);
}
}
private static String inputStreamToString(InputStream inputStream)
{
try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"))
{
return scanner.hasNext() ? scanner.next() : "";
}
}
}
Никаких сторонних зависимостей не требуется.
С набором статического импорта решение Guava может быть очень компактным:
toString(getResource("foo.txt"), UTF_8);
Требуется следующий импорт:
import static com.google.common.io.Resources.getResource
import static com.google.common.io.Resources.toString
import static java.nio.charset.StandardCharsets.UTF_8
package test;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class Main {
public static void 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" FOLDER
public static String getFileFromResources(String fileName) throws Exception {
ClassLoader classLoader = Main.class.getClassLoader();
InputStream stream = classLoader.getResourceAsStream(fileName);
String text = null;
try (Scanner scanner = new Scanner(stream, StandardCharsets.UTF_8.name())) {
text = scanner.useDelimiter("\\A").next();
}
return text;
}
}
По крайней мере, начиная с Apache commons-io 2.5, метод IOUtils.toString () поддерживает аргумент URI и возвращает содержимое файлов, расположенных внутри jar-файлов в classpath:
IOUtils.toString(SomeClass.class.getResource(...).toURI(), ...)
Мне нравится ответ Акосицки с помощью глупого трюка со сканером. Это самое простое из всех, что я вижу, без внешних зависимостей, которое работает в Java 8 (и фактически вплоть до Java 5). Вот еще более простой ответ, если вы можете использовать Java 9 или выше (так как InputStream.readAllBytes()
был добавлен в Java 9):
String text = new String(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());
Guava также имеет, Files.readLines()
если вы хотите, чтобы возвращаемое значение было List<String>
построчно:
List<String> lines = Files.readLines(new File("/file/path/input.txt"), Charsets.UTF_8);
Пожалуйста, обратитесь сюда, чтобы сравнить 3 способа (по BufferedReader
сравнению с Гуавой Files
и Гуавой Resources
), чтобы получить String
из текстового файла.
Charsets
также в Гуаве. Смотрите это: google.github.io/guava/releases/23.0/api/docs
Вот мой подход работал нормально
public String getFileContent(String fileName) {
String filePath = "myFolder/" + fileName+ ".json";
try(InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath)) {
return IOUtils.toString(stream, "UTF-8");
} catch (IOException e) {
// Please print your Exception
}
}
Я написал здесь методы readResource () , чтобы сделать это одним простым вызовом. Это зависит от библиотеки Guava, но мне нравятся методы только для JDK, предложенные в других ответах, и я думаю, что я изменю их таким образом.
Вот решение с использованием Java 11 Files.readString
:
public class Utils {
public static String readResource(String name) throws URISyntaxException, IOException {
var uri = Utils.class.getResource("/" + name).toURI();
var path = Paths.get(uri);
return Files.readString(path);
}
}
Я сделал статический метод NO-зависимости следующим образом:
import java.nio.file.Files;
import java.nio.file.Paths;
public class ResourceReader {
public static String asString(String resourceFIleName) {
try {
return new String(Files.readAllBytes(Paths.get(new CheatClassLoaderDummyClass().getClass().getClassLoader().getResource(resourceFIleName).toURI())));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class CheatClassLoaderDummyClass{//cheat class loader - for sql file loading
}
Мне нравятся утилиты Apache commons для такого типа вещей, и я очень часто использую этот точный вариант использования (чтение файлов из classpath) при тестировании, особенно для чтения файлов JSON /src/test/resources
в рамках модульного / интеграционного тестирования. например
public class FileUtils {
public static String getResource(String classpathLocation) {
try {
String message = IOUtils.toString(FileUtils.class.getResourceAsStream(classpathLocation),
Charset.defaultCharset());
return message;
}
catch (IOException e) {
throw new RuntimeException("Could not read file [ " + classpathLocation + " ] from classpath", e);
}
}
}
В целях тестирования может быть неплохо поймать IOException
и выбросить RuntimeException
- ваш тестовый класс может выглядеть так:
@Test
public void shouldDoSomething () {
String json = FileUtils.getResource("/json/input.json");
// Use json as part of test ...
}
public static byte[] readResoureStream(String resourcePath) throws IOException {
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
InputStream in = CreateBffFile.class.getResourceAsStream(resourcePath);
//Create buffer
byte[] buffer = new byte[4096];
for (;;) {
int nread = in.read(buffer);
if (nread <= 0) {
break;
}
byteArray.write(buffer, 0, nread);
}
return byteArray.toByteArray();
}
Charset charset = StandardCharsets.UTF_8;
String content = new String(FileReader.readResoureStream("/resource/...*.txt"), charset);
String lines[] = content.split("\\n");