Dường như có nhiều cách khác nhau để đọc và ghi dữ liệu của các tệp trong Java.
Tôi muốn đọc dữ liệu ASCII từ một tệp. Những cách có thể và sự khác biệt của họ là gì?
Dường như có nhiều cách khác nhau để đọc và ghi dữ liệu của các tệp trong Java.
Tôi muốn đọc dữ liệu ASCII từ một tệp. Những cách có thể và sự khác biệt của họ là gì?
Câu trả lời:
ASCII là một tệp văn bản, do đó bạn sẽ sử dụng Readers
để đọc. Java cũng hỗ trợ đọc từ tệp nhị phân bằng cách sử dụng InputStreams
. Nếu các tệp đang đọc là rất lớn thì bạn sẽ muốn sử dụng một BufferedReader
đầu trang FileReader
để cải thiện hiệu suất đọc.
Xem qua bài viết này về cách sử dụngReader
Tôi cũng khuyên bạn nên tải xuống và đọc cuốn sách tuyệt vời (nhưng miễn phí) này có tên Thinking In Java
Trong Java 7 :
new String(Files.readAllBytes(...))
(tài liệu) hoặc
Files.readAllLines(...)
Trong Java 8 :
Files.lines(..).forEach(...)
Files.lines(…).forEach(…)
không bảo toàn thứ tự các dòng nhưng được thực thi song song, @Dash. Nếu đơn hàng là quan trọng, bạn có thể sử dụng Files.lines(…).forEachOrdered(…)
, việc này sẽ giữ nguyên đơn hàng (mặc dù không xác minh).
Files.lines(...).forEach(...)
được thực thi song song không? Tôi nghĩ rằng đây chỉ là trường hợp khi bạn rõ ràng tạo luồng song song bằng cách sử dụng Files.lines(...).parallel().forEach(...)
.
forEach
không đảm bảo bất kỳ trật tự nào và lý do là song song dễ dàng. Nếu trật tự được bảo tồn, sử dụng forEachOrdered
.
Cách ưa thích của tôi để đọc một tệp nhỏ là sử dụng BufferedReader và StringBuilder. Nó rất đơn giản và đến mức (mặc dù không đặc biệt hiệu quả, nhưng đủ tốt cho hầu hết các trường hợp):
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
} finally {
br.close();
}
Một số người đã chỉ ra rằng sau Java 7, bạn nên sử dụng các tính năng try-with-resource (nghĩa là tự động đóng):
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
}
Khi tôi đọc các chuỗi như thế này, tôi thường muốn thực hiện một số xử lý chuỗi trên mỗi dòng, vì vậy sau đó tôi sẽ thực hiện việc này.
Mặc dù nếu tôi thực sự chỉ muốn đọc một tệp thành Chuỗi, tôi luôn sử dụng Apache Commons IO với phương thức lớp IOUtils.toString (). Bạn có thể xem nguồn tại đây:
http://www.docjar.com/html/api/org/apache/commons/io/IOUtils.java.html
FileInputStream inputStream = new FileInputStream("foo.txt");
try {
String everything = IOUtils.toString(inputStream);
} finally {
inputStream.close();
}
Và thậm chí đơn giản hơn với Java 7:
try(FileInputStream inputStream = new FileInputStream("foo.txt")) {
String everything = IOUtils.toString(inputStream);
// do something with everything string
}
code
while (dòng! = null) {sb.append (dòng); dòng = br.readLine (); // Chỉ thêm dòng mới khi đường cong KHÔNG phải là dòng cuối cùng .. if (line! = Null) {sb.append ("\ n"); }}code
Cách dễ nhất là sử dụng Scanner
lớp trong Java và đối tượng FileReader. Ví dụ đơn giản:
Scanner in = new Scanner(new FileReader("filename.txt"));
Scanner
có một số phương pháp để đọc theo chuỗi, số, v.v ... Bạn có thể tìm thêm thông tin về điều này trên trang tài liệu Java.
Ví dụ: đọc toàn bộ nội dung thành một String
:
StringBuilder sb = new StringBuilder();
while(in.hasNext()) {
sb.append(in.next());
}
in.close();
outString = sb.toString();
Ngoài ra nếu bạn cần một mã hóa cụ thể, bạn có thể sử dụng mã này thay vì FileReader
:
new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)
BufferedReader
while ((line = br.readLine()) != null) { sb.append(line); }
?
Đây là một giải pháp đơn giản:
String content;
content = new String(Files.readAllBytes(Paths.get("sample.txt")));
Đây là một cách khác để làm điều đó mà không cần sử dụng các thư viện bên ngoài:
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public String readFile(String filename)
{
String content = null;
File file = new File(filename); // For example, foo.txt
FileReader reader = null;
try {
reader = new FileReader(file);
char[] chars = new char[(int) file.length()];
reader.read(chars);
content = new String(chars);
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
reader.close();
}
}
return content;
}
Tôi đã phải điểm chuẩn các cách khác nhau. Tôi sẽ nhận xét về những phát hiện của mình, nhưng nói ngắn gọn, cách nhanh nhất là sử dụng BufferedInputStream cũ đơn giản trên FileInputStream. Nếu nhiều tệp phải được đọc thì ba luồng sẽ giảm tổng thời gian thực hiện xuống khoảng một nửa, nhưng việc thêm nhiều luồng sẽ làm giảm dần hiệu suất cho đến khi hoàn thành thời gian dài hơn ba lần với hai luồng so với chỉ một luồng.
Giả định là bạn phải đọc một tệp và làm một cái gì đó có ý nghĩa với nội dung của nó. Trong các ví dụ ở đây là đọc các dòng từ một bản ghi và đếm những cái có chứa các giá trị vượt quá một ngưỡng nhất định. Vì vậy, tôi giả định rằng Java 8 một lớp Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))
không phải là một tùy chọn.
Tôi đã thử nghiệm trên Java 1.8, Windows 7 và cả ổ SSD và ổ cứng.
Tôi đã viết sáu triển khai khác nhau:
rawPude : Sử dụng BufferedInputStream trên FileInputStream và sau đó cắt các dòng đọc từng byte. Điều này vượt trội hơn bất kỳ cách tiếp cận đơn luồng nào khác, nhưng nó có thể rất bất tiện cho các tệp không phải ASCII.
lineReaderPude : Sử dụng BufferedReader trên FileReader, đọc từng dòng, chia dòng bằng cách gọi String.split (). Đây là chậm hơn khoảng 20% mà rawPude.
lineReaderPudeParallel : Điều này giống như lineReaderPude, nhưng nó sử dụng một số chủ đề. Đây là tùy chọn nhanh nhất tổng thể trong mọi trường hợp.
nioFilesPude : Sử dụng java.nio.files.Files.lines ()
nioAsyncPude : Sử dụng với trình xử lý hoàn thành và nhóm luồng.
nioMemoryMappedPude : Sử dụng tệp ánh xạ bộ nhớ. Đây thực sự là một ý tưởng tồi mang lại thời gian thực hiện lâu hơn ít nhất ba lần so với bất kỳ triển khai nào khác.
Đây là thời gian trung bình để đọc 204 tệp 4 MB trên mỗi ổ i7 và SSD lõi tứ. Các tập tin được tạo ra một cách nhanh chóng để tránh bộ nhớ đệm đĩa.
rawParse 11.10 sec
lineReaderParse 13.86 sec
lineReaderParseParallel 6.00 sec
nioFilesParse 13.52 sec
nioAsyncParse 16.06 sec
nioMemoryMappedParse 37.68 sec
Tôi tìm thấy một sự khác biệt nhỏ hơn tôi mong đợi giữa việc chạy trên ổ SSD hoặc ổ đĩa cứng là SSD nhanh hơn khoảng 15%. Điều này có thể là do các tệp được tạo trên ổ cứng không phân mảnh và chúng được đọc tuần tự, do đó ổ đĩa quay có thể hoạt động gần như một ổ SSD.
Tôi đã rất ngạc nhiên bởi hiệu suất thấp của việc triển khai nioAsyncPude. Hoặc tôi đã triển khai một cái gì đó sai cách hoặc triển khai đa luồng bằng NIO và trình xử lý hoàn thành thực hiện tương tự (hoặc thậm chí tệ hơn) so với triển khai một luồng với API java.io. Ngoài ra, phân tích cú pháp không đồng bộ với CompleteionHandler dài hơn nhiều trong các dòng mã và khó thực hiện chính xác hơn so với triển khai thẳng trên các luồng cũ.
Bây giờ sáu triển khai theo sau là một lớp chứa tất cả chúng cộng với một phương thức main () có thể tham số cho phép chơi với số lượng tệp, kích thước tệp và mức độ tương tranh. Lưu ý rằng kích thước của các tệp khác nhau cộng trừ 20%. Điều này là để tránh bất kỳ ảnh hưởng nào do tất cả các tệp có cùng kích thước.
rawPude
public void rawParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
overrunCount = 0;
final int dl = (int) ';';
StringBuffer lineBuffer = new StringBuffer(1024);
for (int f=0; f<numberOfFiles; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
FileInputStream fin = new FileInputStream(fl);
BufferedInputStream bin = new BufferedInputStream(fin);
int character;
while((character=bin.read())!=-1) {
if (character==dl) {
// Here is where something is done with each line
doSomethingWithRawLine(lineBuffer.toString());
lineBuffer.setLength(0);
}
else {
lineBuffer.append((char) character);
}
}
bin.close();
fin.close();
}
}
public final void doSomethingWithRawLine(String line) throws ParseException {
// What to do for each line
int fieldNumber = 0;
final int len = line.length();
StringBuffer fieldBuffer = new StringBuffer(256);
for (int charPos=0; charPos<len; charPos++) {
char c = line.charAt(charPos);
if (c==DL0) {
String fieldValue = fieldBuffer.toString();
if (fieldValue.length()>0) {
switch (fieldNumber) {
case 0:
Date dt = fmt.parse(fieldValue);
fieldNumber++;
break;
case 1:
double d = Double.parseDouble(fieldValue);
fieldNumber++;
break;
case 2:
int t = Integer.parseInt(fieldValue);
fieldNumber++;
break;
case 3:
if (fieldValue.equals("overrun"))
overrunCount++;
break;
}
}
fieldBuffer.setLength(0);
}
else {
fieldBuffer.append(c);
}
}
}
lineReaderPude
public void lineReaderParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
String line;
for (int f=0; f<numberOfFiles; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
FileReader frd = new FileReader(fl);
BufferedReader brd = new BufferedReader(frd);
while ((line=brd.readLine())!=null)
doSomethingWithLine(line);
brd.close();
frd.close();
}
}
public final void doSomethingWithLine(String line) throws ParseException {
// Example of what to do for each line
String[] fields = line.split(";");
Date dt = fmt.parse(fields[0]);
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCount++;
}
lineReaderPudeParallel
public void lineReaderParseParallel(final String targetDir, final int numberOfFiles, final int degreeOfParalelism) throws IOException, ParseException, InterruptedException {
Thread[] pool = new Thread[degreeOfParalelism];
int batchSize = numberOfFiles / degreeOfParalelism;
for (int b=0; b<degreeOfParalelism; b++) {
pool[b] = new LineReaderParseThread(targetDir, b*batchSize, b*batchSize+b*batchSize);
pool[b].start();
}
for (int b=0; b<degreeOfParalelism; b++)
pool[b].join();
}
class LineReaderParseThread extends Thread {
private String targetDir;
private int fileFrom;
private int fileTo;
private DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private int overrunCounter = 0;
public LineReaderParseThread(String targetDir, int fileFrom, int fileTo) {
this.targetDir = targetDir;
this.fileFrom = fileFrom;
this.fileTo = fileTo;
}
private void doSomethingWithTheLine(String line) throws ParseException {
String[] fields = line.split(DL);
Date dt = fmt.parse(fields[0]);
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCounter++;
}
@Override
public void run() {
String line;
for (int f=fileFrom; f<fileTo; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
try {
FileReader frd = new FileReader(fl);
BufferedReader brd = new BufferedReader(frd);
while ((line=brd.readLine())!=null) {
doSomethingWithTheLine(line);
}
brd.close();
frd.close();
} catch (IOException | ParseException ioe) { }
}
}
}
nioFilesPude
public void nioFilesParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
for (int f=0; f<numberOfFiles; f++) {
Path ph = Paths.get(targetDir+filenamePreffix+String.valueOf(f)+".txt");
Consumer<String> action = new LineConsumer();
Stream<String> lines = Files.lines(ph);
lines.forEach(action);
lines.close();
}
}
class LineConsumer implements Consumer<String> {
@Override
public void accept(String line) {
// What to do for each line
String[] fields = line.split(DL);
if (fields.length>1) {
try {
Date dt = fmt.parse(fields[0]);
}
catch (ParseException e) {
}
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCount++;
}
}
}
nioAsyncPude
public void nioAsyncParse(final String targetDir, final int numberOfFiles, final int numberOfThreads, final int bufferSize) throws IOException, ParseException, InterruptedException {
ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(numberOfThreads);
ConcurrentLinkedQueue<ByteBuffer> byteBuffers = new ConcurrentLinkedQueue<ByteBuffer>();
for (int b=0; b<numberOfThreads; b++)
byteBuffers.add(ByteBuffer.allocate(bufferSize));
for (int f=0; f<numberOfFiles; f++) {
consumerThreads.acquire();
String fileName = targetDir+filenamePreffix+String.valueOf(f)+".txt";
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), EnumSet.of(StandardOpenOption.READ), pool);
BufferConsumer consumer = new BufferConsumer(byteBuffers, fileName, bufferSize);
channel.read(consumer.buffer(), 0l, channel, consumer);
}
consumerThreads.acquire(numberOfThreads);
}
class BufferConsumer implements CompletionHandler<Integer, AsynchronousFileChannel> {
private ConcurrentLinkedQueue<ByteBuffer> buffers;
private ByteBuffer bytes;
private String file;
private StringBuffer chars;
private int limit;
private long position;
private DateFormat frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public BufferConsumer(ConcurrentLinkedQueue<ByteBuffer> byteBuffers, String fileName, int bufferSize) {
buffers = byteBuffers;
bytes = buffers.poll();
if (bytes==null)
bytes = ByteBuffer.allocate(bufferSize);
file = fileName;
chars = new StringBuffer(bufferSize);
frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
limit = bufferSize;
position = 0l;
}
public ByteBuffer buffer() {
return bytes;
}
@Override
public synchronized void completed(Integer result, AsynchronousFileChannel channel) {
if (result!=-1) {
bytes.flip();
final int len = bytes.limit();
int i = 0;
try {
for (i = 0; i < len; i++) {
byte by = bytes.get();
if (by=='\n') {
// ***
// The code used to process the line goes here
chars.setLength(0);
}
else {
chars.append((char) by);
}
}
}
catch (Exception x) {
System.out.println(
"Caught exception " + x.getClass().getName() + " " + x.getMessage() +
" i=" + String.valueOf(i) + ", limit=" + String.valueOf(len) +
", position="+String.valueOf(position));
}
if (len==limit) {
bytes.clear();
position += len;
channel.read(bytes, position, channel, this);
}
else {
try {
channel.close();
}
catch (IOException e) {
}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);
}
}
else {
try {
channel.close();
}
catch (IOException e) {
}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);
}
}
@Override
public void failed(Throwable e, AsynchronousFileChannel channel) {
}
};
THỰC HIỆN RUNNABLE HOÀN TOÀN TẤT CẢ CÁC TRƯỜNG HỢP
https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.java
Dưới đây là ba phương pháp làm việc và thử nghiệm:
BufferedReader
package io;
import java.io.*;
public class ReadFromFile2 {
public static void main(String[] args)throws Exception {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
BufferedReader br = new BufferedReader(new FileReader(file));
String st;
while((st=br.readLine()) != null){
System.out.println(st);
}
}
}
Scanner
package io;
import java.io.File;
import java.util.Scanner;
public class ReadFromFileUsingScanner {
public static void main(String[] args) throws Exception {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
Scanner sc = new Scanner(file);
while(sc.hasNextLine()){
System.out.println(sc.nextLine());
}
}
}
FileReader
package io;
import java.io.*;
public class ReadingFromFile {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("C:\\Users\\pankaj\\Desktop\\test.java");
int i;
while ((i=fr.read()) != -1){
System.out.print((char) i);
}
}
}
Scanner
lớppackage io;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ReadingEntireFileWithoutLoop {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.java");
Scanner sc = new Scanner(file);
sc.useDelimiter("\\Z");
System.out.println(sc.next());
}
}
java.nio.file.Files
? Chúng tôi bây giờ có thể chỉ cần sử dụng readAllLines
, readAllBytes
và lines
.
Các phương thức bên trong org.apache.commons.io.FileUtils
cũng có thể rất tiện dụng, ví dụ:
/**
* Reads the contents of a file line by line to a List
* of Strings using the default encoding for the VM.
*/
static List readLines(File file)
Bạn muốn làm gì với văn bản? Là tập tin đủ nhỏ để phù hợp với bộ nhớ? Tôi sẽ cố gắng tìm cách đơn giản nhất để xử lý tệp cho nhu cầu của bạn. Thư viện FileUtils rất xử lý việc này.
for(String line: FileUtils.readLines("my-text-file"))
System.out.println(line);
org.apache.commons.io.FileUtils
. Liên kết Google có thể thay đổi nội dung theo thời gian, vì ý nghĩa phổ biến nhất sẽ thay đổi, nhưng điều này phù hợp với truy vấn của anh ấy và có vẻ đúng.
readLines(String)
và readLines(File)
không được ủng hộ readLines(File, Charset)
. Mã hóa cũng có thể được cung cấp dưới dạng một chuỗi.
Tôi đã ghi lại 15 cách để đọc một tệp trong Java và sau đó kiểm tra tốc độ của chúng với các kích cỡ tệp khác nhau - từ 1 KB đến 1 GB và đây là ba cách hàng đầu để làm điều này:
java.nio.file.Files.readAllBytes()
Đã thử nghiệm để làm việc trong Java 7, 8 và 9.
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class ReadFile_Files_ReadAllBytes {
public static void main(String [] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
File file = new File(fileName);
byte [] fileBytes = Files.readAllBytes(file.toPath());
char singleChar;
for(byte b : fileBytes) {
singleChar = (char) b;
System.out.print(singleChar);
}
}
}
java.io.BufferedReader.readLine()
Đã thử nghiệm để làm việc trong Java 7, 8, 9.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFile_BufferedReader_ReadLine {
public static void main(String [] args) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
FileReader fileReader = new FileReader(fileName);
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
}
java.nio.file.Files.lines()
Điều này đã được thử nghiệm để hoạt động trong Java 8 và 9 nhưng sẽ không hoạt động trong Java 7 vì yêu cầu biểu thức lambda.
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Stream;
public class ReadFile_Files_Lines {
public static void main(String[] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
File file = new File(fileName);
try (Stream linesStream = Files.lines(file.toPath())) {
linesStream.forEach(line -> {
System.out.println(line);
});
}
}
}
Sử dụng BufferedReader:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
BufferedReader br;
try {
br = new BufferedReader(new FileReader("/fileToRead.txt"));
try {
String x;
while ( (x = br.readLine()) != null ) {
// Printing out each line in the file
System.out.println(x);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
catch (FileNotFoundException e) {
System.out.println(e);
e.printStackTrace();
}
Điều này về cơ bản giống như câu trả lời của Jesus Ramos, ngoại trừ với Tệp thay vì FileReader cộng với phép lặp để chuyển qua nội dung của tệp.
Scanner in = new Scanner(new File("filename.txt"));
while (in.hasNext()) { // Iterates each line in the file
String line = in.nextLine();
// Do something with line
}
in.close(); // Don't forget to close resource leaks
... ném FileNotFoundException
Các lớp luồng được đệm có hiệu suất cao hơn nhiều trong thực tế, đến nỗi API NIO.2 bao gồm các phương thức trả về các lớp luồng này một phần, để khuyến khích bạn luôn sử dụng các luồng được đệm trong ứng dụng của mình.
Đây là một ví dụ:
Path path = Paths.get("/myfolder/myfile.ext");
try (BufferedReader reader = Files.newBufferedReader(path)) {
// Read from the stream
String currentLine = null;
while ((currentLine = reader.readLine()) != null)
//do your code here
} catch (IOException e) {
// Handle file I/O exception...
}
Bạn có thể thay thế mã này
BufferedReader reader = Files.newBufferedReader(path);
với
BufferedReader br = new BufferedReader(new FileReader("/myfolder/myfile.ext"));
Tôi khuyên bạn nên này bài viết để học hỏi những ứng dụng chính của Java NIO và IO.
Có lẽ không nhanh như với I / O được đệm, nhưng khá ngắn gọn:
String content;
try (Scanner scanner = new Scanner(textFile).useDelimiter("\\Z")) {
content = scanner.next();
}
Các \Z
mô hình kể Scanner
rằng delimiter là EOF.
if(scanner.hasNext()) content = scanner.next();
Tôi không thấy nó được đề cập đến trong các câu trả lời khác cho đến nay. Nhưng nếu "Tốt nhất" có nghĩa là tốc độ, thì I / O Java (NIO) mới có thể cung cấp hiệu suất nhanh nhất, nhưng không phải lúc nào cũng dễ dàng nhất để tìm ra ai đó đang học.
http://doad.oracle.com/javase/tutorial/essential/io/file.html
Cách đơn giản nhất để đọc dữ liệu từ một tệp trong Java là sử dụng lớp Tệp để đọc tệp và lớp Máy quét để đọc nội dung của tệp.
public static void main(String args[])throws Exception
{
File f = new File("input.txt");
takeInputIn2DArray(f);
}
public static void takeInputIn2DArray(File f) throws Exception
{
Scanner s = new Scanner(f);
int a[][] = new int[20][20];
for(int i=0; i<20; i++)
{
for(int j=0; j<20; j++)
{
a[i][j] = s.nextInt();
}
}
}
PS: Đừng quên nhập java.util. *; cho Máy quét hoạt động.
Quả ổi cung cấp một lớp lót cho việc này:
import com.google.common.base.Charsets;
import com.google.common.io.Files;
String contents = Files.toString(filePath, Charsets.UTF_8);
Đây có thể không phải là câu trả lời chính xác cho câu hỏi. Đó chỉ là một cách khác để đọc một tệp mà bạn không chỉ định rõ ràng đường dẫn đến tệp của mình trong mã Java và thay vào đó, bạn đọc nó dưới dạng đối số dòng lệnh.
Với đoạn mã sau,
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class InputReader{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s="";
while((s=br.readLine())!=null){
System.out.println(s);
}
}
}
chỉ cần tiếp tục và chạy nó với:
java InputReader < input.txt
Điều này sẽ đọc nội dung của input.txt
và in nó ra bàn điều khiển của bạn.
Bạn cũng có thể thực hiện System.out.println()
ghi vào một tệp cụ thể thông qua dòng lệnh như sau:
java InputReader < input.txt > output.txt
Điều này sẽ đọc từ input.txt
và viết cho output.txt
.
Bạn có thể sử dụng readAllLines và join
phương thức để lấy toàn bộ nội dung tệp trong một dòng:
String str = String.join("\n",Files.readAllLines(Paths.get("e:\\text.txt")));
Nó sử dụng mã hóa UTF-8 theo mặc định, đọc dữ liệu ASCII chính xác.
Ngoài ra, bạn có thể sử dụng readAllBytes:
String str = new String(Files.readAllBytes(Paths.get("e:\\text.txt")), StandardCharsets.UTF_8);
Tôi nghĩ readAllBytes nhanh hơn và chính xác hơn, bởi vì nó không thay thế dòng mới bằng \n
và dòng mới cũng có thể \r\n
. Nó phụ thuộc vào nhu cầu của bạn mà phù hợp.
Đối với các ứng dụng web Maven dựa trên JSF, chỉ cần sử dụng ClassLoader và Resources
thư mục để đọc trong bất kỳ tệp nào bạn muốn:
Đặt phần phụ thuộc IO Commons IO vào POM của bạn:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
Sử dụng mã bên dưới để đọc nó (ví dụ bên dưới đang đọc trong tệp .json):
String metadata = null;
FileInputStream inputStream;
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
inputStream = (FileInputStream) loader
.getResourceAsStream("/metadata.json");
metadata = IOUtils.toString(inputStream);
inputStream.close();
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return metadata;
Bạn có thể làm tương tự cho các tệp văn bản, tệp .properations, lược đồ XSD , v.v.
Sử dụng nụ hôn Java nếu đây là về sự đơn giản của cấu trúc:
import static kiss.API.*;
class App {
void run() {
String line;
try (Close in = inOpen("file.dat")) {
while ((line = readLine()) != null) {
println(line);
}
}
}
}
import java.util.stream.Stream;
import java.nio.file.*;
import java.io.*;
class ReadFile {
public static void main(String[] args) {
String filename = "Test.txt";
try(Stream<String> stream = Files.lines(Paths.get(filename))) {
stream.forEach(System.out:: println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Chỉ cần sử dụng java 8 Stream.
try {
File f = new File("filename.txt");
Scanner r = new Scanner(f);
while (r.hasNextLine()) {
String data = r.nextLine();
JOptionPane.showMessageDialog(data);
}
r.close();
} catch (FileNotFoundException ex) {
JOptionPane.showMessageDialog("Error occurred");
ex.printStackTrace();
}
Phương thức trực quan nhất được giới thiệu trong Java 11 Files.readString
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String args[]) throws IOException {
String content = Files.readString(Paths.get("D:\\sandbox\\mvn\\my-app\\my-app.iml"));
System.out.print(content);
}
}
PHP có sự xa xỉ này từ nhiều thập kỷ trước! ☺
Mã này tôi đã lập trình nhanh hơn nhiều cho các tệp rất lớn:
public String readDoc(File f) {
String text = "";
int read, N = 1024 * 1024;
char[] buffer = new char[N];
try {
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr);
while(true) {
read = br.read(buffer, 0, N);
text += new String(buffer, 0, read);
if(read < N) {
break;
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
return text;
}
+=
theo cách này cung cấp cho bạn độ phức tạp bậc hai (!) cho một nhiệm vụ phải là độ phức tạp tuyến tính. điều này sẽ bắt đầu thu thập dữ liệu cho các tập tin trong một vài mb. để giải quyết vấn đề này, bạn nên giữ các chuỗi văn bản trong danh sách <chuỗi> hoặc sử dụng trình tạo chuỗi đã nói ở trên.
String fileName = 'yourFileFullNameWithPath';
File file = new File(fileName); // Creates a new file object for your file
FileReader fr = new FileReader(file);// Creates a Reader that you can use to read the contents of a file read your file
BufferedReader br = new BufferedReader(fr); //Reads text from a character-input stream, buffering characters so as to provide for the efficient reading of characters, arrays, and lines.
Tập hợp dòng trên có thể được viết thành 1 dòng đơn như:
BufferedReader br = new BufferedReader(new FileReader("file.txt")); // Optional
Thêm vào trình tạo chuỗi (Nếu tệp của bạn rất lớn, bạn nên sử dụng trình tạo chuỗi khác, sử dụng đối tượng Chuỗi bình thường)
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
} finally {
br.close();
}