Có tiện ích nào giúp đọc tệp văn bản trong tài nguyên thành Chuỗi không. Tôi cho rằng đây là một yêu cầu phổ biến, nhưng tôi không thể tìm thấy bất kỳ tiện ích nào sau khi Google.
Có tiện ích nào giúp đọc tệp văn bản trong tài nguyên thành Chuỗi không. Tôi cho rằng đây là một yêu cầu phổ biến, nhưng tôi không thể tìm thấy bất kỳ tiện ích nào sau khi Google.
Câu trả lời:
Vâng, ổi cung cấp điều này trong Resources
lớp. Ví dụ:
URL url = Resources.getResource("foo.txt");
String text = Resources.toString(url, StandardCharsets.UTF_8);
getResource
đang sử dụng Resource.class.getClassLoader
nhưng trong các ứng dụng web, đây có thể không phải là trình tải lớp "của bạn", vì vậy nên sử dụng (ví dụ như trong [1]) Thread.currentThread().getContextClassLoader().getResourceAsStream
thay vào đó (tham khảo [1]: stackoverflow.com/questions/676250/ từ )
Resources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8)
đó đảm bảo việc sử dụng trình nạp lớp chính xác.
com.google.common.io.Resources
được đánh dấu là không ổn định theo SonarQube
guava
đã thay đổi việc thực hiện. Đối với ổi 23 việc thực hiện như sau. ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
Bạn có thể sử dụng thủ thuật Stool Scanner cũ để thực hiện điều đó mà không cần phụ thuộc thêm như ổi:
String text = new Scanner(AppropriateClass.class.getResourceAsStream("foo.txt"), "UTF-8").useDelimiter("\\A").next();
Các bạn, đừng sử dụng công cụ của bên thứ 3 trừ khi bạn thực sự cần điều đó. Có rất nhiều chức năng trong JDK.
CartApplication.class.getResourceAsStream
để CartApplication.class.getClassLoader().getResourceAsStream
tải tài nguyên trong jar hiện tại..như srm / test / resource
Đối với java 7:
new String(Files.readAllBytes(Paths.get(getClass().getResource("foo.txt").toURI())));
getClass().getClassLoader()
nhưng giải pháp tuyệt vời!
Phương pháp đơn giản dưới đây sẽ hoạt động tốt nếu bạn đang sử dụng Java 8 trở lên:
/**
* 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()));
}
}
}
Và nó cũng hoạt động với các tài nguyên trong các tệp jar .
Về mã hóa văn bản: InputStreamReader
sẽ sử dụng bộ ký tự hệ thống mặc định trong trường hợp bạn không chỉ định. Bạn có thể muốn tự chỉ định nó để tránh các vấn đề giải mã, như thế này:
new InputStreamReader(isr, StandardCharsets.UTF_8);
Luôn luôn thích không phụ thuộc vào các thư viện lớn, chất béo. Trừ khi bạn đang sử dụng Guava hoặc Apache Commons IO cho các tác vụ khác, việc thêm các thư viện đó vào dự án của bạn chỉ để có thể đọc từ tệp có vẻ hơi quá.
Tôi hiểu rằng Java thuần túy không làm tốt công việc khi thực hiện các nhiệm vụ đơn giản như thế này. Chẳng hạn, đây là cách chúng ta đọc từ một tệp trong Node.js:
const fs = require("fs");
const contents = fs.readFileSync("some-file.txt", "utf-8");
Đơn giản và dễ đọc (mặc dù mọi người vẫn thích dựa vào nhiều phụ thuộc dù sao, chủ yếu là do sự thiếu hiểu biết). Hoặc trong Python:
with open('some-file.txt', 'r') as f:
content = f.read()
Thật đáng buồn, nhưng nó vẫn đơn giản đối với các tiêu chuẩn của Java và tất cả những gì bạn phải làm là sao chép phương thức trên vào dự án của bạn và sử dụng nó. Tôi thậm chí không yêu cầu bạn hiểu những gì đang diễn ra ở đó, bởi vì nó thực sự không quan trọng với bất cứ ai. Nó chỉ hoạt động, giai đoạn :-)
InputStream
biến is
là null
hay không.
Quả ổi có phương thức "toString" để đọc tệp thành Chuỗi:
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);
Phương thức này không yêu cầu tệp phải nằm trong đường dẫn lớp (như trong câu trả lời trước của Jon Skeet ).
String stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
yegor256 đã tìm thấy một giải pháp hay bằng cách sử dụng 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()
vào chuỗi phương thức: String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
apache-commons-io có một tên tiện ích FileUtils
:
URL url = Resources.getResource("myFile.txt");
File myFile = new File(url.toURI());
String content = FileUtils.readFileToString(myFile, "UTF-8"); // or any other encoding
Tôi thường có vấn đề này bản thân mình. Để tránh phụ thuộc vào các dự án nhỏ, tôi thường viết một hàm tiện ích nhỏ khi tôi không cần commons io hoặc tương tự. Đây là mã để tải nội dung của tệp trong bộ đệm chuỗi:
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());
Việc chỉ định mã hóa rất quan trọng trong trường hợp đó, bởi vì bạn có thể đã chỉnh sửa tệp của mình trong UTF-8, sau đó đặt nó vào một cái lọ và máy tính mở tệp có thể có mã CP-1251 làm mã hóa tệp gốc của nó (ví dụ) ; Vì vậy, trong trường hợp này, bạn không bao giờ biết mã hóa đích, do đó thông tin mã hóa rõ ràng là rất quan trọng. Ngoài ra, vòng lặp để đọc tệp char bằng char có vẻ không hiệu quả, nhưng nó được sử dụng trên BufferedReader, và do đó thực sự khá nhanh.
Bạn có thể sử dụng mẫu mã Java sau đây
new String(Files.readAllBytes(Paths.get(getClass().getResource("example.txt").toURI())));
Nếu bạn muốn lấy Chuỗi của mình từ tài nguyên dự án như tệp testcase / foo.json trong src / main / resource trong dự án của bạn, hãy làm điều này:
String myString=
new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("testcase/foo.json").toURI())));
Lưu ý rằng phương thức getClassLoader () bị thiếu trong một số ví dụ khác.
Sử dụng FileUtils của Apache. Nó có một phương thức readFileToString
Tôi đang sử dụng cách sau để đọc các tệp tài nguyên từ 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() : "";
}
}
}
Không yêu cầu phụ thuộc của bên thứ ba.
Với bộ nhập tĩnh, giải pháp Guava có thể rất nhỏ gọn một lớp:
toString(getResource("foo.txt"), UTF_8);
Nhập khẩu sau đây là bắt buộc:
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;
}
}
Ít nhất là với Apache commons-io 2.5, phương thức IOUtils.toString () hỗ trợ một đối số URI và trả về nội dung của các tệp nằm trong các tệp trên đường dẫn lớp:
IOUtils.toString(SomeClass.class.getResource(...).toURI(), ...)
Tôi thích câu trả lời của akosicki với Thủ thuật quét ngu ngốc. Đó là cách đơn giản nhất mà tôi thấy mà không cần phụ thuộc bên ngoài hoạt động trong Java 8 (và trên thực tế hoàn toàn trở lại Java 5). Đây là một câu trả lời thậm chí đơn giản hơn nếu bạn có thể sử dụng Java 9 trở lên (kể từ khi InputStream.readAllBytes()
được thêm vào Java 9):
String text = new String(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());
Quả ổi cũng có Files.readLines()
nếu bạn muốn giá trị trả về là List<String>
từng dòng:
List<String> lines = Files.readLines(new File("/file/path/input.txt"), Charsets.UTF_8);
Vui lòng tham khảo tại đây để so sánh 3 cách ( BufferedReader
so với Guava Files
so với Guava Resources
) để lấy String
từ tệp văn bản.
Charsets
cũng ở ổi. Xem điều này: google.github.io/guava/release/23.0/api/docs
Đây là cách tiếp cận của tôi làm việc tốt
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
}
}
Tôi đã viết các phương thức readResource () ở đây , để có thể thực hiện nó trong một lệnh gọi đơn giản. Nó phụ thuộc vào thư viện Guava, nhưng tôi thích các phương thức chỉ có JDK được đề xuất trong các câu trả lời khác và tôi nghĩ tôi sẽ thay đổi những cách này.
Đây là một giải pháp sử dụng 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);
}
}
Tôi đã thực hiện phương pháp tĩnh KHÔNG phụ thuộc như thế này:
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
}
Tôi thích các tiện ích chung của Apache cho loại công cụ này và sử dụng rộng rãi trường hợp sử dụng chính xác này (đọc các tệp từ đường dẫn lớp) khi kiểm tra, đặc biệt là để đọc các tệp JSON từ /src/test/resources
một phần của kiểm tra đơn vị / tích hợp. ví dụ
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);
}
}
}
Đối với mục đích thử nghiệm, thật tuyệt khi bắt IOException
và ném RuntimeException
- lớp thử nghiệm của bạn có thể trông giống như, ví dụ
@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");