- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们处理巨大的文件(有时每个文件 50 GB)。应用程序读取这一文件,并根据业务逻辑,写入多个输出文件(4-6)。
文件中的记录长度可变,记录中的每个字段均由分隔符分隔。
据了解,使用带有 ByteBuffer 的 FileChannel 读取文件总是比使用 BufferedReader.readLine 然后使用分隔符分割更好。
下面是我们如何使用文件 channel 读取:
使用这种使用 FileChannel 读取文件的方法需要 57 分钟来处理文件。
我们想减少这个时间,并尝试使用 BufferredReader.readLine(),然后使用分隔符分割,看看效果如何。
令人震惊的是,同一个文件仅用了 7 分钟就完成了处理。
这里有什么问题?为什么 FileChannel 比缓冲读取器花费更多时间,然后使用字符串分割。
我一直假设 ReadLine 和 Split 组合会对性能产生很大的影响?
如果我以错误的方式使用 FileChannel,有人可以指出吗?一个
提前致谢。希望我已经正确总结了这个问题。
下面是示例代码:
while (inputByteBuffer.hasRemaining() && (b = inputByteBuffer.get()) != 0){
boolean endOfField = false;
if (b == 10){
break;
}
else{
if (b == 94){//^
if (!inputByteBuffer.hasRemaining()){
inputByteBuffer.clear();
noOfBytes = inputFileChannel.read(inputByteBuffer);
inputByteBuffer.flip();
}
if (inputByteBuffer.hasRemaining()){
byte b2 = inputByteBuffer.get();
if (b2 == 124){//|
if (!inputByteBuffer.hasRemaining()){
inputByteBuffer.clear();
noOfBytes = inputFileChannel.read(inputByteBuffer);
inputByteBuffer.flip();
}
if (inputByteBuffer.hasRemaining()){
byte b3 = inputByteBuffer.get();
if (b3 == 94){//^
String field = new String(fieldBytes, 0, index, encoding);
if(fieldIndex == -1){
fields = new String[sizeFromAConfiguration];
}else{
fields[fieldIndex] = field;
}
fieldBytes = new byte[maxFieldSize];
endOfField = true;
fieldIndex++;
}
else{
fieldBytes = addFieldBytes(fieldBytes, b, index);
index++;
fieldBytes = addFieldBytes(fieldBytes, b2, index);
index++;
fieldBytes = addFieldBytes(fieldBytes, b3, index);
}
}
else{
endOfFile = true;
//fields.add(new String(fieldBytes, 0, index, encoding));
fields[fieldIndex] = new String(fieldBytes, 0, index, encoding);
fieldBytes = new byte[maxFieldSize];
endOfField = true;
}
}else{
fieldBytes = addFieldBytes(fieldBytes, b, index);
index++;
fieldBytes = addFieldBytes(fieldBytes, b2, index);
}
}else{
endOfFile = true;
fieldBytes = addFieldBytes(fieldBytes, b, index);
}
}
else{
fieldBytes = addFieldBytes(fieldBytes, b, index);
}
}
if (!inputByteBuffer.hasRemaining()){
inputByteBuffer.clear();
noOfBytes = inputFileChannel.read(inputByteBuffer);
inputByteBuffer.flip();
}
if (endOfField){
index = 0;
}
else{
index++;
}
}
最佳答案
常量 hasRemaining()
造成了大量开销/read()
检查以及常量 get()
来电。 get()
可能会更好将整个缓冲区放入数组并直接处理,只需调用 read()
当你到达终点时。
要回答评论中的问题,您不应分配新的 ByteBuffer
每次阅读。这很贵。继续使用同一个。请注意,不使用 DirectByteBuffer
对于这个应用程序。这是不合适的:仅当您希望数据位于 JVM/JNI 边界以南时才合适,例如仅在 channel 之间复制时。
但我想我会扔掉它,或者更确切地说,使用 BufferedReader.read()
重写它。 ,而不是 readLine()
接下来是字符串分割,并使用与此处大致相同的逻辑,当然,除了您不需要继续调用 hasRemaining()
并填充缓冲区,BufferedReader
会自动为您完成。
您必须小心存储 read()
的结果进入int
,并在每个 read()
之后检查它是否为 -1 .
我不清楚您是否应该使用 Reader
事实上,除非你知道你有多字节文本。可能是一个简单的BufferedInputStream
会更合适。
关于Java FileChannel 与 BufferedReader - Spring Batch - Reader,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49061304/
我正在考虑更改 this question进入我的情况。然后我决定我的情况需要自己的问题并希望得到答案。在调用 FileChannel.truncate() 减小文件大小后,我调用 FileChann
我已阅读关于 FileChannel 的 transferFrom 的评论 * This method is potentially much more efficient than a simp
我必须按照小端顺序写一个整数。所以我创建了一个带有 FileChannel 属性和一些写入方法的类(此类不扩展任何内容)。 但是有一个问题:只有一种方法有效,另一种无效! 这里是工作方法(dis是Fi
以下是我将一个文件附加到另一个文件的方法。 public static void appendFile(File baseFile, File newFile) throws IOException
我正在创建一个 fileChannel 来执行内存映射写入。该文件 channel 的大小为 100 字节。我只向其中写入 80 个字节。因此,当我稍后读取该文件时,它会在 and 上添加 5 个“0
我有一个 IO 类,它使用 ByteBuffer 来缓冲对 FileChannel 的访问(因此它基本上在构造函数中接受 FileChannel)。我想对它进行单元测试,所以如果我能得到一个字节数组支
我是 Java NIO 新手。我发现 FileChannel 对象具有读取和写入方法。但我无法在单个时间点使用相同的 FileChannel 进行读写。有没有办法做到这一点? 最佳答案 从具有“rw”
使用 FileChannel.position() 从不同线程写入一个文件是否安全?这对于分段下载是必需的。每个线程都会写入其在文件中的位置,即线程的位置不会相交。 最佳答案 虽然单个选项是线程安全的
在读取大文件时,我从这段代码中得到了一些奇怪的输出,该文件是使用 while 循环打印到 99,999 位数的,但是,在读取文件并打印内容时,它只输出 99,988 行。另外,使用 ByteBuffe
我正在使用fileChannel.lock(long position, long size, boolean shared)获得文件特定部分的独占访问权限。具体代码为: fileChannel.lo
我尝试使用 FileChannel 将特定字节写入文件的特定位置。但实际上文件缩小到我写更改的最后位置。我这样做: Path path = Paths.get("I://music - Cop
我正在使用 FileChannel 将 2MB 数据写入文件。 private void write(int numEntries, int entrySize) throws Exc
我有一个管道,我需要从中读取数据。但是,正如我在阅读之前所了解的那样,我必须创建一定大小的缓冲区。问题是如何定义缓冲区的大小以从管道读取所有数据? 这是我的代码: RandomAccessFile a
我正在尝试使用以下方法连接一组文本文件。但是,只有第一个文件显示在输出文件中。 public void concatenateFiles(List fileLocations, String outp
当我执行以下类(class)时 import java.io.*; import java.nio.*; import java.nio.file.*; import java.nio.channel
我目前正在开发一个应用程序,需要随机访问许多(60k-100k)相对较大的文件。由于打开和关闭流是一项相当昂贵的操作,因此我更愿意将最大文件的 FileChannel 保持打开状态,直到不再需要它们为
我正在使用 RandomAccessFile 打开大文件(~ 200 MB),然后获取它的 Channel。我正在尝试将一些数据映射到 MappedByteBuffer,但出现异常: Channel
文件 a.txt 看起来像: ABC 文件 d.txt 看起来像: DEF 我正在尝试获取“DEF”并将其附加到“ABC”,因此 a.txt 看起来像 ABC DEF 我尝试过的方法总是完全覆盖第一个
对于我的特定任务,我需要从 FileChannel 中读取数据到 Stream (或 Collection )属于 String的。 在常规 NIO对于 Path我们可以使用一个方便的方法Files.
我想我误解了 FileChannel 的锁定功能是如何工作的。 我想在一个文件上拥有独占写入锁,但允许从任何进程读取。 在运行 Java 7 的 Windows 7 机器上,我可以使用 FileCha
我是一名优秀的程序员,十分优秀!