randomaccessfile类-读/写linkedhashmap的第一项时出现问题

mjqavswn  于 2021-09-13  发布在  Java
关注(0)|答案(0)|浏览(128)

以下是主要代码:

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {

        RandomAccessFile raf = new RandomAccessFile("test.dat", "rwd");
        Map<String, String> dictionary = new LinkedHashMap<>();
        Map<String, IndexRecord> mapThatWritesToFile = new LinkedHashMap<>();
        Map<String, IndexRecord> mapThatReadsFromFile = new LinkedHashMap<>();
//        dictionary.put("Test", "test");
        dictionary.put("Java", "Best programming language");
        dictionary.put("T-SQL", "Database language");
        dictionary.put("None", "Doesn't matter");

        int pointerToDictionaryData = Integer.BYTES; // I add 4 bytes, because this number is going to be the first data written to file.
        int tempPointer = pointerToDictionaryData;
        for(String part : dictionary.keySet()){
            pointerToDictionaryData += part.getBytes().length + (2*Integer.BYTES); // adding bytes from String + 2x Integer.Bytes for startByte and length of data.
        }
        raf.writeInt(pointerToDictionaryData);

        int pointerToIndex = (int) raf.getFilePointer();
        raf.seek(pointerToDictionaryData);
        for(String key : dictionary.keySet()){
            StringBuilder sb = new StringBuilder(key);
            sb.append("=");
            sb.append(dictionary.get(key));
            raf.writeUTF(sb.toString());

            IndexRecord record = new IndexRecord(tempPointer, (int) (raf.getFilePointer() - tempPointer));
            mapThatWritesToFile.put(key, record);
            tempPointer = (int) raf.getFilePointer();
        }

        raf.seek(pointerToIndex);
        for(String key : mapThatWritesToFile.keySet()){
           raf.writeUTF(key);
           raf.writeInt(mapThatWritesToFile.get(key).getStart());
           raf.writeInt(mapThatWritesToFile.get(key).getLength());
        }

        raf.seek(0);
        pointerToDictionaryData = raf.readInt();

        while(raf.getFilePointer() < pointerToDictionaryData){
            String key = raf.readUTF();
            int start = raf.readInt();
            int length = raf.readInt();
            mapThatReadsFromFile.put(key, new IndexRecord(start, length));
        }

        for(String key : mapThatReadsFromFile.keySet()){
            System.out.println("Reading: " + key);
            System.out.println(key + " | starts at byte: " + mapThatReadsFromFile.get(key).getStart() +
                    " and is " + mapThatReadsFromFile.get(key).getLength() + " bytes long");
            raf.seek(mapThatReadsFromFile.get(key).getStart());
            System.out.println("Result: " + raf.readUTF() + "\n");
        }
    }
}

这里还有一个必要的indexrecord类:

public class IndexRecord {

    private int start;
    private int length;

    public IndexRecord(int start, int length) {
        this.start = start;
        this.length = length;
    }

    public int getStart() {
        return start;
    }

    public int getLength() {
        return length;
    }
}

那么到底是什么问题呢?也许我会从这个节目的目的开始。我试图学习如何使用randomaccessfile类,我创建了一个代码,将三个部分写入一个文件。
第一个是指向存储字典元素的文件部分的指针(格式为key=description)。在那之后,我存储了关于index的数据——这是一个linkedhashmap,其中的键与dictionary中使用的键相同,它的值是indexrecord示例,它包含两个整数值:第一个是指向一个字节的指针,关于这个键的数据从该字节开始,第二个是该信息的长度(也以字节为单位)。文件的最后一部分存储有关字典的信息。
所以这个程序的要点是我不想把每个字典元素都加载到内存中。我只想加载索引,每当我需要字典键的描述时,我都会使用索引记录从文件中加载所需的数据。
好吧,那有什么问题?问题是,无论是读还是写字典的第一个元素,总有一些错误。如果运行该程序,您将看到“java”的值的长度错误,并且它也不会读取该键的值。如果您取消对字典的“test,test”输入的注解,您将发现java的值现在已正确读取,并且长度没有问题,但“test”键的数据再次出现错误。
字典中带有注解的“test”示例的结果:

Reading: Java
Java | starts at byte: 4 and is 69 bytes long
Result: Java

Reading: T-SQL
T-SQL | starts at byte: 73 and is 25 bytes long
Result: T-SQL=Database language

Reading: None
None | starts at byte: 98 and is 21 bytes long
Result: None=Doesn't matter

与字典中未注解的“test”示例的结果相比:

Reading: Test
Test | starts at byte: 4 and is 60 bytes long
Result: Test

Reading: Java
Java | starts at byte: 64 and is 32 bytes long
Result: Java=Best programming language

Reading: T-SQL
T-SQL | starts at byte: 96 and is 25 bytes long
Result: T-SQL=Database language

Reading: None
None | starts at byte: 121 and is 21 bytes long
Result: None=Doesn't matter

所以,正如您所看到的,字典的第一个元素的长度总是有问题,并且没有正确地阅读(或者之前没有正确地编写)。
如果问题太大,我很抱歉,但是我想包括所有重要的信息,这样你就可以很好地了解这个程序是什么,它做什么,问题是什么。
ps:我知道一些“解决方案”可能是在字典中添加一个元素作为第一个无法读取的元素,但我不想这样做。我想了解代码的错误,以便更好地理解这个类。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题