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);
}
}
}
读线器面板
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++;
}
读线器ParseParallel
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) { }
}
}
}
niofilesparse文件解析
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++;
}
}
}
异步解析
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) {
}
};
28条答案
按热度按时间jyztefdp16#
只需使用Java8流。
cdmah0mi17#
在java中,从文件中读取数据最简单的方法是使用file类读取文件,使用scanner类读取文件的内容。
ps:别忘了导入java.util.*;让扫描器工作。
hpcdzsge18#
最直观的方法是在Java11中引入的
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);
}
}
bbmckpt719#
我最喜欢的读取小文件的方法是使用bufferedreader和stringbuilder。它非常简单而且切中要害(虽然不是特别有效,但对于大多数情况来说已经足够好了):
有人指出,在java 7之后,您应该使用try with resources(即自动关闭)功能:
当我读到这样的字符串时,我通常希望每行都进行一些字符串处理,所以我开始使用这个实现。
如果我真的想把一个文件读入一个字符串,我总是使用ApacheCommonsIO类ioutils.tostring()方法。您可以在这里查看源代码:
http://www.docjar.com/html/api/org/apache/commons/io/ioutils.java.html
使用java 7更简单:
ubof19bj20#
下面是用Java8方法实现的一行代码。假设
text.txt
文件位于eclipse的项目目录的根目录中。5anewei621#
如果这是为了简化结构,请使用java kiss:
pxy2qtax22#
下面是不使用外部库的另一种方法:
ajsxfq5m23#
我不得不用不同的方法来衡量。我将对我的发现发表评论,但简而言之,最快的方法是在fileinputstream上使用普通的旧bufferedinputstream。如果必须读取许多文件,那么三个线程将把总执行时间减少到大约一半,但是添加更多的线程将逐渐降低性能,直到使用二十个线程比只使用一个线程要花三倍的时间才能完成。
假设您必须读取一个文件并对其内容做一些有意义的事情。在这里的示例中,从日志中读取行,并对包含超过某个阈值的值的行进行计数。所以我假设一行Java8
Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))
不是一个选择。我在Java1.8、Windows7以及ssd和hdd驱动器上进行了测试。
我写了六个不同的实现:
rawparse:在fileinputstream上使用bufferedinputstream,然后逐字节剪切读取的行。这比任何其他单线程方法都好,但对于非ascii文件来说可能非常不方便。
linereaderparse:在文件读取器上使用bufferedreader,逐行读取,通过调用string.split()拆分行。这比以前慢了大约20%。
linereaderparseparallel:这与linereaderparse相同,但它使用多个线程。这是所有情况下最快的选择。
niofilesparse:使用java.nio.files.files.lines()
nioasyncparse:使用带有完成处理程序和线程池的asynchronousfilechannel。
niomemorymappedparse:使用内存Map文件。这是一个非常糟糕的主意,它的执行时间至少比任何其他实现长三倍。
这是读取204个文件(共4个)的平均时间 四核i7和ssd驱动器上各有mb。文件是动态生成的,以避免磁盘缓存。
我发现在ssd上运行和在hdd驱动器上运行之间的差别比我预期的要小大约快15%。这可能是因为这些文件是在一个无碎片的hdd上生成的,并且它们是按顺序读取的,因此旋转驱动器可以像ssd一样执行。
我对nioasyncparse实现的低性能感到惊讶。要么我以错误的方式实现了某些东西,要么使用nio和完成处理程序的多线程实现的性能与使用java.ioapi的单线程实现相同(甚至更差)。此外,使用completionhandler的异步解析在代码行中要比在旧流上直接实现长得多,而且很难正确实现。
现在,这六个实现后跟一个包含它们的类,再加上一个可参数化的main()方法,该方法允许处理文件数量、文件大小和并发度。请注意,文件大小在正负20%之间变化。这是为了避免由于所有文件的大小完全相同而产生任何影响。
原始解析
读线器面板
读线器ParseParallel
niofilesparse文件解析
异步解析
所有案例的全面实施
https://github.com/sergiomt/javaiobenchmark/blob/master/filereadbenchmark.java
zmeyuzjn24#
下面是一个简单的解决方案:
2cmtqfgy25#
以下是三种工作和测试方法:
使用bufferedreader
使用扫描仪
使用filereader
使用scanner类在没有循环的情况下读取整个文件
kqlmhetl26#
使用bufferedreader:
sgtfey8w27#
cactoos为您提供了一个声明性的一行代码:
l5tcr1uw28#
最简单的方法是使用
Scanner
类和filereader对象。简单示例:StringBuilder sb = new StringBuilder();
while(in.hasNext()) {
sb.append(in.next());
}
in.close();
outString = sb.toString();
new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)