Java 我们如何知道记录是否已经被读取?我们如何跟踪记录指针?

Java 我们如何知道记录是否已经被读取?我们如何跟踪记录指针?,java,file,file-io,io,nio,Java,File,File Io,Io,Nio,我对处理文件的相关算法感到困惑。 根据我的在线研究,表示可变长度记录的标准方法是沿数据放置元数据,例如记录的长度。此外,如果我们希望以某种顺序保存记录,我们还可以将指向下一条记录的指针存储为记录字段的一部分。 让我们以一个文件为例,其中记录的形式为,这与我上面描述的内容一致。 我看到的代码片段通常在内存缓冲区中读取文件的一部分,我想这是有道理的。例如: ByteBuffer copy = ByteBuffer.allocate(SIZE); FileChannel fc = FileChan

我对处理文件的相关算法感到困惑。
根据我的在线研究,表示可变长度记录的标准方法是沿数据放置元数据,例如记录的长度。此外,如果我们希望以某种顺序保存记录,我们还可以将指向下一条记录的指针存储为记录字段的一部分。
让我们以一个文件为例,其中记录的形式为
,这与我上面描述的内容一致。
我看到的代码片段通常在内存缓冲区中读取文件的一部分,我想这是有道理的。例如:

ByteBuffer copy = ByteBuffer.allocate(SIZE);  
FileChannel fc = FileChannel.open(file, READ, WRITE);  
int nread;  
do {  
   nread = fc.read(copy);  
} while (nread != -1 && copy.hasRemaining());  
我认为这或多或少是一种在内存中读取文件部分的方法<代码>大小可以是包含多个记录的大小

问题:当内存中有X个记录时,我们如何知道要读取的特定记录是否在缓冲区中?示例:如果我有指向下一条记录的指针,我如何知道该特定记录已作为缓冲区的一部分加载,或者我必须从文件中读取更多数据?
这一部分在教科书中提到是很简单的,但我不知道这是如何实现的

要明确的是:用Java提供一个示例代码将非常棒!!!但对我来说,用伪代码或清晰的算法清楚地解释这个暗点也是很好的

更新:
更清楚地说:
如果我在数组[N]中读取了N条记录。如果我读取记录
array[0]
,然后获取
array[0].pointerToNext
,例如文件中的
0x123A
。我怎么知道:
1) 如果缓冲区中已读取位置
0x123A
中的记录,即
数组[n]


2) 缓冲区中此记录的索引是什么?

在文件中,记录指针通常存储为记录索引或文件位置。因此,您可以根据文件中的当前位置推断是否已经读取了特定记录

在您的示例中,您可以使用变量pos跟踪文件位置:

int pos = 0;
int nread;  
do {  
   nread = fc.read(copy);
   if(nread == -1) {
      break;
   } else {
      pos += nread;
   }
} while (copy.hasRemaining());  

您将需要边读边读数据,并将其与您的阅读结合起来。这是解决这个问题的一种方法,也许我会这样做

// read a made up database
// untested

public class SimpleDatabaseRead {

    public void main(String[] args) {
        if (args == null || args.length == 0) {
            System.out.println("no file");
            return;
        }

        try {
            File file = new File(args[0]);
            FileInputStream in = null;

            try {
                in = new FileInputStream(file);

                // rec length will be 16-bit unsigned
                // large array OK, only 64KiB in mem
                byte[] bytes = new byte[65536];

                int bread = 0;
                long fpos = 0, next = 0;

                char[][] rec;

                while ((bread = in.read(bytes, 0, 4)) != -1) {
                    fpos += bread;

                    // length of this rec in bytes
                    int len = ((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF);

                    // num entries in rec, for convenience
                    int entries = ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF);

                    if (in.read(bytes, 0, len) != len)
                        break;
                    fpos += len;

                    rec = new char[entries][];

                    for (int i = 0, k = 0, h; i < entries; i++) {
                        rec[i] = new char[
                            ((bytes[k++] & 0xFF) << 8) | (bytes[k++] & 0xFF)];

                        for (h = 0; h < rec[i].length && k < len; h++)
                            rec[i][h] = ((bytes[k++] & 0xFF) << 8) | (bytes[k++] & 0xFF);
                    }

                    for (char[] rec : recs)
                        System.out.println("record: " + new String(rec));

                    if (in.read(bytes, 0, 4) != len)
                        break;
                    fpos += bread;

                    // 48-bit file marker of next rec
                    next = ((bytes[0] & 0xFF) << 32)
                         | ((bytes[1] & 0xFF) << 24)
                         | ((bytes[2] & 0xFF) << 24)
                         |  (bytes[3] & 0xFF);

                    if (next < fpos) {
                        in.close();
                        in = new FileInputStream(file);
                        in.skip(fpos = next);
                    }
                }

            } finally {
                if (in != null) in.close();
            }
            System.out.println("read ended");

        } catch (IOException e) {
            System.out.println(e.getMessage());
        } catch (FileNotFoundsException e) {
            System.out.println(e.getMessage());
        }
    }
}
//读取一个组成的数据库
//未经测试
公共类SimpleDatabaseRead{
公共void main(字符串[]参数){
if(args==null | | args.length==0){
System.out.println(“无文件”);
返回;
}
试一试{
File File=新文件(args[0]);
FileInputStream in=null;
试一试{
in=新文件输入流(文件);
//rec长度将为16位无符号
//大型阵列正常,内存中只有64KiB
字节[]字节=新字节[65536];
int=0;
长fpos=0,下一个=0;
char[][]rec;
while((bread=in.read(字节,0,4))!=-1){
fpos+=面包;
//此rec的长度(字节)

int len=((字节[0]&0xFF)在读取文件时,您需要以某种方式解释数据。读取长度和/或指针,并跟踪读取的字节数和/或读卡器的位置,以找到起始点。此外,您还可以存储某种标识符作为数据的一部分。@Radiodef:您的意思是以某种方式将缓冲区大小与记录指针关联起来?是的,您可以uld可以这样做。要么这样做,要么使其足够大,以使整个记录适合存在重叠的缓冲区。或者读取部分记录。但底线是以某种方式跟踪所有记录。所有InputStream派生都有一个带长度参数的读取,因此如果将长度存储在文件。@Radiodef:我丢失了一点。如果我在缓冲区中索引为0的记录具有下一条记录的指针值
0x1234
,我如何知道该文件位置的记录是否在缓冲区中读取?从文件中的流位置中减去它,看看它前面或后面有多远。如果这些记录不按顺序显示,则在文件中,最好的方法是做一些IMO的事情:java不幸的是通常没有一个有效的查找方法。在代码<代码> POS < /代码> <代码> > 循环位于文件的部分之后,我们读了这个部分。特定记录已读取?使用
pos
如何找到缓冲区中的索引?您的问题是:“如果位置0x123A中的记录已在缓冲区中读取”。对此的检查将是pos>0x123A。具体取决于您(re)的方式使用缓冲区,您可能只使用缓冲区位置,而不是显式跟踪文件位置。+1:我想我明白您的意思,但我不确定您对位设置做了什么。特别是因为括号错误,例如
int len=((字节[0]&0xFF)他们是对的。
&0xFF
是字节值的掩码。在移位之前必须这样做,否则字节会通过符号扩展自动升级为整数。如果在移位之前不进行掩码,将得到非常虚假的结果。下面的链接显示了同样的情况:本页上的第一个图表显示了字节是如何得到的符号扩展为int:虽然该页面是关于右移的。但为什么要这样做?条目数是多少?
条目数是为了方便实例化值数组。存储元素数和字符串长度可以让您非常方便地存储所有不同长度的字符串数组。这是一个非常有用的答案。事实上,你的答案现在开始让我思考,在我们的应用程序中定义页面和块是否是一种标准做法,类似于操作系统。请参阅我的其他(相关)问题