得到文件某行的偏移量(get byte offset of a line)

得到文件某行的偏移量(get byte offset of a line)

场景:通过对文件的一趟处理,把每行的offset得到。

现有的文件系统不能直接定位到某一行,如果你知道行号,也只能一行行的读下去,找到你想要的line。但是当文件很大的时候,就需要一定的预处理,保存行的offset,后续的处理可以根据offset直接定位到具体的line,无疑这会提高速度。所以需要实现:line到byte offset的映射。

Google了一番,没有发现可用的代码,但是思想是显而易见的:按字节顺序读取文件,然后读到行分割符的时候做相应处理,然而知易行难。

Read line by line

第一个想法是:每次读一行,然后行的长度可以用来更新offset,如下:

public void init() throws Exception {
        // Scan the file to construct the data structure for use
        file = new File(path);
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line = null;
        entries = new Entry[this.lines()];
        int k = 0;
        int offset = 0;
        while ((line = reader.readLine()) != null) {
            line = line.replace("\"", "");
            int len = line.length();
            String cells[] = line.split(",");
            int startIP = IPv4Util.ip2int(cells[0]);
            int endIP = IPv4Util.ip2int(cells[1]);
            //System.out.println("==" + startIP + "-" + endIP);
            Entry entry = new Entry(startIP, endIP,  offset);
            entries[k++] = entry;

            // NB.这里存在问题,因为offset是字节级别的,而字符串和特定编码有关
            offset += len;
        }
    }

问题在于:字符串的编码是容易变动的,所以字节级别最通用。

Read byte by byte

每次读取一个字节,在遇到换行的时候我们根据读到的字节数更新offset,同时需要一个buffer保存此次读取到的line。

public void init2() throws Exception {
        entries = new ArrayList<Entry>();
        // Scan the file to construct the data structure for use
        RandomAccessFile raf = new RandomAccessFile(path, "r");
        byte buffer[] = new byte[1024]; //buf this current line
        int b;
        // raf.length();
        int offset = 0;
        int bytesRead = 0;
        int bufferIndex = 0;
        while((b = raf.read()) != -1){
            // buffer it first
            buffer[bufferIndex++] = (byte)b; // int to byte
            bytesRead ++ ;

            if(b == ‘\n‘){
                String line = new String(buffer);
                line = line.replace("\"", "");
                //System.out.println(line);
                int len = line.length();
                String cells[] = line.split(",");
                int startIP = IPv4Util.ip2int(cells[0]);
                int endIP = IPv4Util.ip2int(cells[1]);
                //System.out.println("==" + startIP + "-" + endIP + ", " + offset);
                Entry entry = new Entry(startIP, endIP,  offset);
                entries.add(entry);

                // reset
                bufferIndex = 0;
                Arrays.fill(buffer, (byte)0);

                offset += bytesRead;// prepare offset for next entry
                bytesRead = 0;
            }
        }
    }

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-09 13:15:56

得到文件某行的偏移量(get byte offset of a line)的相关文章

Linux wc命令用于计算文件的行数/字数

利用wc指令我们可以计算文件的Byte数.字数.或是行数,若不指定文件名称.或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据. 语法: wc [-clw] [--help] [--version] [文件...] 参数: -c或--bytes或--chars 只显示Bytes数. -l或--lines 只显示行数. -w或--words 只显示字数. --help 在线帮助. --version 显示版本信息. 实例: 在默认的情况下,wc将计算指定文件的行数.字数,以及

MyEclipse导入Maven项目pom文件第一行报错,运行Tomcat报Log4j错误--解决方法

问题描述: 前一段时间电脑第一次导入Maven项目,又是pom文件错,改好后又是运行Tomcat报Log4j错误,一直倒腾了近一个月程序才成功跑起来,太不容易. 也上网查了很长时间,没一个方法能解决我的问题的.特记下解决方法,希望能帮到像我这样的web刚入门者. (刚入门,肯定有说的不对的地方,有错也希望能指出来,我改正) 前期操作:导入项目后clean,install,update,中会报错(因为我已经解决了,所以没有×). 两问题对应解决方法: 1.pom文件第一行大红叉,说明是项目的文件指

python 代码统计文件的行数

#!/usr/bin/python #encofing:utf8 # 统计文件的行数 import sys def lineCount(fd): n = 0 for i in fd: n += 1 return n fd = sys.stdin print lineCount(fd)

使用java读取文件夹中文件的行数

使用java统计某文件夹下所有文件的行数 经理突然交代一个任务:要求统计某个文件夹下所有文件的行数.在网上查了一个多小时没有解决.后来心里不爽就决定自己写一个java类用来统计文件的行数,于是花了两个小时将代码写出(可见我的java功底还是挺烂的).虽然有很多有待改进的地方,依然有纪念意义. 本java类的核心是通过BufferedReader类的readLine()方法,间接的统计行数:通过递归遍历文件. 这个类只是写来完成任务的.结果不是很严谨,许多情况并没考虑到:比如判断想读取某一类文件怎

根据一列数据 抽取另一个文件的行数据

方法一: 使用awk处理,先读入文件中的一列数据,然后在第二文件中做判断 awk -F'\t' 'FILENAME=="commUsers_Hotel"{F[$0]=1}FILENAME=="Hotel3"{if($0 in F){print}}' commUsers_Hotel Hotel3 > fugai 根据一列数据 抽取另一个文件的行数据,布布扣,bubuko.com

java 文件按行读写

1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.File; 4 import java.io.FileReader; 5 import java.io.FileWriter; 6 import java.io.IOException; 7 8 public class Demo001 { 9 10 public static void writeFile(String strSr

能把opencv的源码也进行调试吗?(需要pdb文件才行)

能把opencv的源码也进行调试吗?(需要pdb文件才行)1.我是用的Qt Creator,然后"工具\选项\调试器\概要\源码路径映射"中,选择"添加Qt源码",目标路径是Qt的源码路径,比如是"C:\Qt\Qt5.7.0\5.7\Src", 源路径是Qt Creator自动补充的.2.按照这种方法也可以将VC CRT源码给添加进来,目标路径是VC CRT的源码路径,比如是"C:\Program Files (x86)\Microso

Linux下的split 命令(将一个大文件根据行数平均分成若干个小文件)

将一个大文件分成若干个小文件方法 例如将一个BLM.txt文件分成前缀为 BLM_ 的1000个小文件,后缀为系数形式,且后缀为4位数字形式 先利用 wc -l BLM.txt       读出 BLM.txt 文件一共有多少行 再利用 split 命令 split -l 2482 ../BLM/BLM.txt -d -a 4 BLM_ 将 文件 BLM.txt 分成若干个小文件,每个文件2482行(-l 2482),文件前缀为BLM_ ,系数不是字母而是数字(-d),后缀系数为四位数(-a 4

bash 取文件特定行

比如,想要取某文件10-20行 可以用sed sed -n '10,20p' XXX.txt 非常方便!