如何在文件中标记字符串?

时间:2010-02-27 15:11:47

标签: java

我有一个文本文件。它的设计如下:

#1{1,12,345,867}
#2{123, 3243534, 2132131231} 
#3{234, 35345}
#4{}

... (在每个条目的末尾代表“\ n”)

这是一个例子。实际上我的字符串#number {number,number,...,number}可能真的很长......

以下是使用此文件的类的构造函数的模板:

public Submatrix(String matrixFilePath, int startPos, int endPos) throws FileNotFoundException{

}

如您所见,子矩阵由startPos和endPos矩阵的字符串数决定。

我的问题是:“我如何计算字符串以达到合适的字符串?” 我的文件可以包含数十亿个字符串。我应该使用LineNumberReader-> readLine()数十亿次?????

4 个答案:

答案 0 :(得分:5)

我很想顺序读取每一行,直到我到达所需的行。但是,由于这些行在文件中编号并用换行符分隔,因此您可以将该文件视为随机访问并采用各种策略。例如,您可以使用二进制搜索的变体来快速查找起始行。您可以估算前N行的平均线长,然后尝试对起始位置进行更准确的猜测,依此类推。

答案 1 :(得分:2)

我认为答案是肯定的,你使用readLine阅读了数十亿行,除非你认为使用其中任何一行都是值得的

  • GregS概述的策略,即估算线路长度并使用它来开始读取正确线路附近的某处,或
  • 您使用单独的索引,无论是在文件的开头还是在一个非常可预测的单独文件中,就像

    0000001 000000001024
    0000002 000000001064
    0000003 000000002010
    

    也就是说,该行的行号和起始位置以字节为单位,以严格定义的方式使得可以通过以下方式确定索引的位置:

    我想阅读第3行,所以通过转到位置(3-1)* 20找到第3行的位置, 并阅读0000003 000000002010,解析并知道第3行位于字节位置2010,寻找该位置并开始阅读。

    如果它位于主数据文件中,则计算或维护索引可能并不容易,因为这意味着您在实际编写文件之前预先计算了位置。我想我会使用一个单独的索引文件,并在写入期间计算索引,或者有一个单独的实用程序来创建给定数据文件的索引文件。

编辑添加了示例代码以演示我的提案

我制作了一个小的Python脚本,它读取数据文件并创建索引文件。索引文件包含数据文件中一行的位置,可以轻松搜索。

此示例脚本的索引格式为06d,这对于999.999行数据文件来说已经足够了,因为它可能需要进行调整(不要忘记INDEX_LENGTH)。它创建一个索引文件,并使用该索引文件从数据文件中读取给定的行(出于演示目的;您将使用java作为该部分:)

脚本调用如:

python create_index.py data.txt data.idx 3

我的示例数据文件是:

#1{1,12,345,867}
#2{123, 3243534, 2132131231}
#3{234, 35345}
#4{}

并且脚本本身是:

import sys

# Usage: python this_script.py datafile indexfile lineno
# indexfile will be overwritten
# lineno is the data line which will be printed using the
# index file, as a demonstration
datafilename= sys.argv[1]
indexfilename = sys.argv[2]
lineno = int(sys.argv[3])

# max 999999 lines in this format
format = "%06d\n"
INDEX_LENGTH = 6+1 # +1 for newline


def create_indexfile():
        indexfile = open(indexfilename, "wB")
        # Print index of first line
        indexfile.write(format % 0)

        f = open(datafilename, "rB")
        line = f.readline()
        while len(line) > 0:
                indexfile.write( format % f.tell() )
                line = f.readline()
        f.close()
        indexfile.close()

# Retrieve the data of 1 line in the data file
# using the index file
def get_line():
        linepos = INDEX_LENGTH * (lineno - 1)

        indexfile = open(indexfilename, "rB")
        indexfile.seek(linepos)
        datapos = int(indexfile.readline())
        indexfile.close()

        datafile = open(datafilename, "rB")
        datafile.seek(datapos)
        print datafile.readline()
        datafile.close()


if __name__ == '__main__':
        create_indexfile()
        get_line()

在更改数据文件后,需要重建索引文件。您可以通过将读取的数据(#3 {...})中的行号与输入行号进行比较来验证您是否读取了正确的数据,因此它非常安全。

无论您是否选择使用它,我认为这个例子非常简单明了。

答案 2 :(得分:1)

@extraneon

这是我想用来表示字符串#number {number,number,...}

的类
package logic;

public class DenominatedBinaryRow{
private int sn;
private BinaryRow row;

public DenominatedBinaryRow(int sn, BinaryRow row){
    this.sn = sn;
    this.row = row;
}

public DenominatedBinaryRow plus(int sn, DenominatedBinaryRow addend){
    return new DenominatedBinaryRow(sn, this.row.plus(addend.row));
}

public int getSn(){
    return this.sn;
}

public BinaryRow getRow(){
    return this.row;
}

public boolean equals(Object obj){
    DenominatedBinaryRow res = (DenominatedBinaryRow) obj;
    if (this.getSn() == res.getSn() && this.getRow().equals(res.getRow())){
        return true;
    }
    return false;
}

 }

将序列化它可能是有效的,而不是将BinaryRow(它的实现如下)转换为字符串? 如果我将它的许多实例序列化为文件,我将如何反序列化必要的字符串(必要的实例)? (希望,我理解你的问题)

package logic;

import java.util.*;

public class BinaryRow {
private List<Integer> row;

public BinaryRow(){
    this.row = new ArrayList<Integer>();
}

public List<Integer> getRow(){
    return this.row;
}

public void add(Integer arg){
    this.getRow().add(arg);
}

public Integer get(int index){
    return this.getRow().get(index);
}

public int size(){
    return this.getRow().size();
}


public BinaryRow plus(BinaryRow addend){
    BinaryRow result = new BinaryRow();

    //suppose, rows are already sorted (ascending order)
    int i = this.size();
    int j = addend.size();
    while (i > 0 && j > 0)
        if (this.get(this.size() - i) < addend.get(addend.size() - j)){
            result.add(this.get(this.size() - i));
            i--;
        }
        else if (this.get(this.size() - i) > addend.get(addend.size() - j)){
            result.add(addend.get(addend.size() - j));
            j--;
        }
        else{
            result.add(this.get(this.size() - i));
            i--;
            j--;
        }

    if (i > 0){
        for (int k = this.size() - i; k < this.size(); k++)
            result.add(this.get(k));
    }
    if (j > 0){
        for (int k = addend.size() - j; k < addend.size(); k++)
            result.add(addend.get(k));
    }

    return result;
}

public boolean equals(Object obj){
    BinaryRow binRow = (BinaryRow) obj;
    if (this.size() == binRow.size()){
        for (int i = 0; i < this.size(); i++){
            if (this.getRow().get(i) != binRow.getRow().get(i)) return false;
        }
        return true;
    }
    return false;
}

public long convertToDec(){
    long result = 0;
    for (Integer next : this.getRow()) {
        result += Math.pow(2, next);
    }

    return result;
}

}

答案 3 :(得分:-1)

我很害怕你必须到第x行,你必须调用readLine()x次。 这意味着在您到达此行之前读取所有数据。每个字符都可以是一个行结束,所以如果不读取该行之前的每个字符,就无法进入第x行。