我目前正在使用JOGL(Java OpenGL绑定)开发3D图形应用程序.简而言之,我有一个巨大的横向二进制文件.由于它的大小,我必须在运行时流式传输地形块.因此,我们明确地看到随机访问问题.我已经完成了第一个(和脏:))实现(也许它是多线程的),我正在使用一个愚蠢的方法......这是它的初始化:
dataInputStream = new DataInputStream(new BufferedInputStream(fileInputStream,4 * 1024);
dataInputStream.mark(dataInputStream.available());
Run Code Online (Sandbox Code Playgroud)
当我需要读取(流)特殊块(我已经在文件中知道它的"偏移量")时,我正在执行以下操作(对我感到羞耻:)):
dataInputStream.reset();
dataInputStream.skipBytes(offset);
dataInputStream.read(whatever I need...);
Run Code Online (Sandbox Code Playgroud)
因为我没有经验,这是我能想到的第一件事:)所以,直到现在我已经阅读了3篇有用且非常有趣的文章(我建议你阅读它们,或许如果你对这个主题感兴趣的话)
字节缓冲区和非堆内存 - 格雷戈里先生似乎在Java NIO中识字.
Java技巧:如何快速阅读文件 [http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly] - 这是一个有趣的基准.
文章:调优Java I/O性能 [http://java.sun.com/developer/technicalArticles/Programming/PerfTuning/] - 简单的Sun建议,但请向下滚动并查看那里的"随机访问"部分; 它们显示了RandomAccessFile(RAF)的简单实现,具有自缓冲改进.
格雷戈里先生在他的文章末尾提供了几个*.java文件.其中之一是FileChannel + ByteBuffer + Mapping(FBM)和RAF之间的基准测试.他说,与英国皇家空军相比,他在使用FBM时注意到了4倍的加速.我在以下条件下运行此基准:
结果令人震惊:
英国皇家空军大约28秒! FBM约0.2秒!
但是,他在这个基准测试中实现RAF并没有自我缓冲(第3篇文章讲述了一个),所以我猜这是调用的"RandomAccessFile.seek"方法,他们如此努力地降低了性能.
好的,现在经过我所学到的所有这些事情,有1个问题和1个困境:)
问题:当我们使用"FileChannel.map"映射文件时,Java是否将整个文件内容复制到MappedByteBuffer中?或者它只是模仿它?如果它复制,那么使用FBM方法不适合我的情况,是吗?
困境:取决于你对这个问题的答案......
如果映射复制文件,那么我似乎只有2个可能的解决方案:RAF +自缓冲(第3篇文章中的那个)或者使用FileChannel中的位置(不使用映射)...哪一个会会更好?
如果映射不复制文件,那么我有3个选项:前两个和FBM本身.
编辑:这是另外一个问题.你们有些人说,映射不会将文件复制到MappedByteBuffer中.那么,为什么我不能映射1GB文件呢,我收到"无法映射"的消息......
PS我想通过建议得到满意的答案,因为我无法在互联网上找到关于此主题的一致信息.
谢谢 :)
我需要从一个固定大小的集合中随机均匀地采样一个数字,进行一些计算,然后将新数字放回集合中.(所需的样本数量非常大)
我试图将数字存储在列表中并使用random.choice()来选择一个元素,将其删除,然后附加新元素.但那太慢了!
我想将数字存储在一个numpy数组中,对一个索引列表进行采样,并为每个索引执行计算.
我注意到,java.io和java.nio随机访问文件的实施对于略有不同如何FileLocks进行处理.
看起来好像(在Windows上)java.io为您提供强制文件锁定,并java.nio在分别请求时为您提供建议文件锁定.强制文件锁定意味着锁定适用于所有进程,并且建议适用于遵循相同锁定协议的良好行为进程.
如果我运行以下示例,我可以*.nio手动删除该文件,而*.io文件拒绝删除.
import java.io.*;
import java.lang.management.ManagementFactory;
import java.nio.*;
import java.nio.channels.*;
import java.nio.file.*;
public class NioIoLock {
public static void main(String[] args) throws IOException, InterruptedException {
String workDir = System.getProperty("user.dir");
FileChannel channelIo, channelNio;
FileLock lockIo, lockNio;
// use io
{
String fileName = workDir
+ File.separator
+ ManagementFactory.getRuntimeMXBean().getName()
+ ".io";
File lockFile = new File(fileName);
lockFile.deleteOnExit();
RandomAccessFile file = new RandomAccessFile(lockFile, "rw");
channelIo = file.getChannel();
lockIo …Run Code Online (Sandbox Code Playgroud) 我正在对我正在使用的库进行一些更改。为了减少内存使用,库将其临时数据写入磁盘而不是将其保存在内存中。然而,对于我的使用场景来说,将其保留在内存中会更有效。它还存在一些并发问题,因为它的临时文件具有常量名称,因此不能在不同线程中同时运行(因为线程会损坏彼此的数据)。
因此,我需要更改库,以便将所有数据保留在内存中。我最初并没有编写该库,因此我不太愿意对代码进行大幅更改。因此,我希望通过尽可能少的重构来做到这一点。写入磁盘的代码非常简单。这是一个(稍微简化的)示例:
final FileChannel fileChannel = this.randomAccessFile.getChannel();
fileChannel.position(calculatePosition());
while (blockData.hasRemaining())
{
fileChannel.write(blockData);
}
Run Code Online (Sandbox Code Playgroud)
块的读取非常相似(即它使用从 RandomAccessFile 获取的 FileChannel)。
感觉最简单的解决方案是如果我可以使用 FileChannel 的某种实现,它映射到内存中的某个位置而不是文件。我知道我可以使用 FileChannel 的映射方法将文件映射到内存中的某个位置。然而,事实恰恰相反。这给了我一个文件的“内存API”。我想要一个针对某些内存的 FileChannel 接口。有没有可用的实现?
我以前从未接触过Java IO API的经验,现在我真的很沮丧.我发现很难相信它有多奇怪和复杂,做一个简单的任务有多难.
我的任务:我有2个位置(起始字节,结束字节),pos1和pos2.我需要读取这两个字节之间的行(包括起始字节,不包括结尾字节),并将它们用作UTF8字符串对象.
例如,在大多数脚本语言中,它将是一个非常简单的1-2-3-liner(在Ruby中,但它对于Python,Perl等基本相同):
f = File.open("file.txt").seek(pos1)
while f.pos < pos2 {
s = f.readline
# do something with "s" here
}
Run Code Online (Sandbox Code Playgroud)
使用Java IO API很快就会出现问题;)实际上,我看到了两种\n从常规本地文件中读取行(以...结尾)的方法:
getFilePointer()和seek(long pos),但它的readLine()读取非UTF8字符串(甚至不是字节数组),但非常奇怪的字符串具有破坏的编码,并且它没有缓冲(这可能意味着每个read*()调用都将被转换为单个不连续的OS read()= >相当慢).readLine()方法,它甚至可以进行一些搜索skip(long n),但它无法确定已经读取的偶数字节数,也没有提到文件中的当前位置.我试过用类似的东西:
FileInputStream fis = new FileInputStream(fileName);
FileChannel fc = fis.getChannel();
BufferedReader br = new BufferedReader(
new InputStreamReader(
fis,
CHARSET_UTF8
)
);
Run Code Online (Sandbox Code Playgroud)
...然后使用fc.position()获取当前文件读取位置并fc.position(newPosition)设置一个,但它似乎在我的情况下不起作用:看起来它返回由BufferedReader完成的缓冲区预填充的位置,或类似的东西 - …
编辑: 以下代码已被修改为工作,因为问题已解决.
具体来说,(*hardwareList.next_item)->next最初是在没有括号的情况下编写的(例如as *hardwareList.next_item->next),编译器也不理解它.
我正在努力解决为什么编译器与我的C代码混淆.我正在尝试创建一个存储所有项目的链接列表,以及指向最后一个"下一个"变量的地址的指针,以便于追加.
typedef struct {
int recordNum;
char toolName[25];
int quantity;
float cost;
} HardwareData;
typedef struct _HardwareListItem{
HardwareData data;
struct _HardwareListItem* next;
} HardwareListItem;
typedef struct _HardwareList {
HardwareListItem* items;
HardwareListItem** next_item;
} HardwareList;
HardwareList readFromFile(FILE* fp)
{
char stopReading = 0;
HardwareList hardwareList = {0};
hardwareList.next_item = &hardwareList.items;
do {
*hardwareList.next_item = (HardwareListItem*)calloc(1, sizeof(HardwareData));
if (*hardwareList.next_item == NULL)
{
fprintf(stderr, "OOM Reading File\n");
fflush(stderr);
exit(EXIT_FAILURE);
}
if (fread(&((*hardwareList.next_item)->data), sizeof(HardwareData), 1, fp) != …Run Code Online (Sandbox Code Playgroud) 是否可以通过RandomAccessFile将光标定位到文件中特定行的开头?
例如,我想在文件中第111行的char 10到20之间更改String.该文件具有固定长度的记录.
是否可以使用RandomAccessFile将光标直接定位到第111行的开头?
更新:
我使用了以下代码.但是,它返回null.
行长度为200个字符(如果我没有错,则为200个字节)
File f = new File(myFile);
RandomAccessFile r = new RandomAccessFile(f,"rw");
r.skipBytes(200 * 99); // linesize * (lineNum - 1)
System.out.println(r.readLine());
Run Code Online (Sandbox Code Playgroud)
我哪里错了?
我理解随机访问迭代器如何对连续容器起作用std::vector:迭代器只是维护一个指向当前元素的指针,并且任何加法/减法都应用于指针.
但是,我对于如何为非连续容器实现类似的功能感到困惑.我对如何std::deque:iterator工作的第一个猜测是,它维护了一个指向它包含的连续内存组的表的指针,但我不确定.
典型的标准库如何实现这一点?
什么是让GPU有效地计算"反功能"例程的最佳模式,这通常取决于定位的内存写入而不是读取?例如.比如计算直方图,排序,按百分比划分数字,将不同大小的数据合并到列表等中.
让我们举个例子来简化它.我构建了一个构造函数采用的列表integer和a List<Integer>.我的列表将包含给定列表的所有元素乘以integer.我的列表不存储新元素,而是动态计算它们:
class MyList extends AbstractList<Integer> implements RandomAccess {
private final int multiplier;
private final List<Integer> list;
public MyList(int multiplier, List<Integer> list) {
this.multiplier = multiplier;
this.list = list;
}
@Override
public Integer get(int index) {
return list.get(index) * multiplier;
}
@Override
public int size() {
return list.size();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我们可以调用new MyList(3, list)与list = [0, 1, 2, 3]获得[0, 3, 6, 9].
我想限制开发人员给MyList构造函数一个列表,这也是RandomAccess为了确保他不会破坏性能.
我尝试用以下方法更改构造函数:
public <E …Run Code Online (Sandbox Code Playgroud) random-access ×10
java ×6
nio ×3
c ×1
c++ ×1
collections ×1
deque ×1
file ×1
filechannel ×1
filelock ×1
glsl ×1
gpgpu ×1
gpu ×1
iterator ×1
java-io ×1
linked-list ×1
list ×1
numpy ×1
opengl ×1
performance ×1
python ×1
random ×1
streaming ×1