在两个点之间读取文件

3
我有以下文件:
文件.csv
header:2013/01/01, shasum: 495629218484151218892233214
content:data,a,s,d,f,g,h,j,k,l
content:data,q,w,e,r,t,y,u,i,o,p
content:data,z,x,c,v,b,n,m
footer:2013/01/01 EOF

我需要计算内容的哈希值。换句话说,我需要在不包括文件头和尾的情况下计算文件内容的哈希值,并确保它与源头中提供的哈希值匹配。我尝试使用scanner逐行读取文件并去除文件头和尾。

Scanner reader = new Scanner(new FileReader("filename"));
String header = reader.nextLine();
while(reader.hasNextLine()){
    line = reader.nextLine();
    if(reader.hasNextLine()){
        md.update(line.getBytes());
        md.update(NEW_LINE.getBytes());
    }
}

我不知道文件来自哪里,可能来自Windows或Unix。那么我如何知道使用什么NEW_LINE呢?为此,我写了这个“肮脏的Hack”。

int i;
while((i = br.read()) != -1){
    if(i == '\r'){
        if(br.read() == '\n'){
            NEW_LINE = "\r\n";
            break;
        }
    } else if(i == '\n'){
        NEW_LINE = "\n";
        break;
    }
}

基本上,它正在寻找第一个序列要么是\r\n要么是\n。它遇到的第一个字符被认为是换行符。
如果我的文件同时包含CRLF和LF,这肯定会给我带来麻烦。我可能会从读取器中受益,向其提供两个偏移量,它会将两个偏移量之间的内容返回给我。像这样:reader.read(15569, 236952265); 我相信我想要的两个偏移量是可以计算出来的。非常感谢社区的任何建议。

为什么不要将CRLF和LF包含在哈希中?无论你期望什么。 - Archer
2
我认为他希望哈希值对于相同文件在任何系统的换行标准下都是相同的。 - BlackVegetable
1
如果您有Unix和Windows源代码,非ASCII字符也会给您带来麻烦。 - artbristol
@archer,我们需要Sha-224哈希而不是md5。问题出在“md.update(line)”中,“line”字符串可以从“Scanner.nextLine()”或“BufferedReader.readline()”获取。在这两种情况下,“line”都被截断了,换行符没有被保留。 - Juzer Ali
1
也许这很天真,但是难道没有一种读取它的方法吗?也许通过反转字节流并正常使用Scanner可以实现?因此,您可以向后解析它,删除您消耗的页脚,将此修改后的文件暂时保存,然后向前读取它。这不是一个非常好的解决方案,但我认为这是可能的... - BlackVegetable
显示剩余9条评论
1个回答

1
比我在评论中想象的要好,我们应该简单地使用RandomAccessFile类!
// Load in the data file in read-only mode:
RandomAccessFile randFile = new RandomAccessFile("inputFileName.txt", "r");

// (On your own): Calculate starting byte to read from
// (On your own): Calculate ending byte to read from

// Discard header and footer.
randFile.setLength(endingPoint);
randFile.seek(startingPoint);

// Discard newlines of any kind as they are read in.
StringBuilder sb = new StringBuilder(endingPoint - startingPoint);
String currentLine = "";
while(currentLine != null)
{
  sb.append(currentLine);
  currentLine = randFile.readLine();
}

// hash your String contained in your StringBuilder without worrying about
// header, footer or newlines of any kind.

请注意,此代码不是生产质量,因为它没有捕获异常并可能存在一些偏移错误。我强烈建议阅读RandomAccessFile类的文档:http://docs.oracle.com/javase/1.4.2/docs/api/java/io/RandomAccessFile.html#readLine()
希望这可以帮到您。如果我说错了,请告诉我,我会再试一次。

我的问题不是内容开头或结尾的换行符。我的问题是在内容中间的所有换行符。randFile.readLine()会去掉行末的换行符,因此它不会被包含在哈希值中。我在标头中收到的哈希值已经包括了换行符。 - Juzer Ali
@juzerali 哦,那很容易解决。你需要使用readFully(),它会给你指定数组中的所有字节。我以为你也想从正文中删除换行符。 - BlackVegetable
如果文件大小太大,我会遇到麻烦。在我们的情况下,我们预计文件中会有超过70k行。我想我必须编写一个算法来一次读取几个块。 - Juzer Ali
@juzerali,你只需要担心哈希函数。每次读取几个块的算法不应该太难。只需将代码从使用readFully()调整为使用read(),它会一次读取一个字节,或者重载版本会根据您告诉它的字节数读取。这些都在我发布链接的javadoc中。 - BlackVegetable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接