【问题标题】:Reading file between two points在两点之间读取文件
【发布时间】:2013-01-16 16:19:47
【问题描述】:

我有以下文件:

文件.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 包含在您的哈希中?不管你期望什么
  • 我认为他希望哈希值与任一系统的换行标准中的同一文件相同。
  • 你不能消耗 15569 个字符然后忽略它们吗?从那时起,您可以继续,直到到达终点...?
  • 如果你有 Unix 和 Windows 源代码,你也会遇到非 ASCII 字符的问题
  • 也许这很幼稚,但不应该有一种方法可以向后阅读吗?也许通过反转字节流并正常使用扫描仪?因此,您可以向后解析它,删除您使用的页脚,临时保存这个修改过的文件,然后向前阅读。不是一个很好的解决方案,但我认为这是可能的......

标签: java io newline readfile


【解决方案1】:

比我在 cmets 中想象的要好,我们应该简单地使用 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() 将在行尾剔除新行字符,因此它不会包含在哈希中。我在标题中收到的哈希值是用包含换行符计算的。
  • @juzerali 哦,这很容易解决。您需要使用 readFully() 它将为您提供您指定的数组中的所有字节。我以为你也想从正文中删除换行符。
  • 如果文件太大,会给我带来麻烦。在我们的例子中,我们期望文件中有超过 70k 行。我想我将不得不编写一个算法来一次读取几个块。
  • @juzerali 您的哈希函数就是您需要担心的全部。一次读取几块的算法应该不会太糟糕。只需将代码从使用 readFully() 调整为 read() ,它将一次读取一个字节,或者重载版本将读取您告诉它的尽可能多的字节。这一切都在我发布链接的 javadoc 中。
猜你喜欢
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多