在不同的操作系统中读取新行字符

Sai*_*sif 0 java vim file-io

我遇到过一种情况,我正在读取一些日志文件,然后通过以下代码片段计算我遇到的行数.

byte[] c = new byte[1024];
long count = 0;
int readChars = 0;
while ((readChars = is.read(c)) != -1) {
    for (int i = 0; i < readChars; ++i) {
        if (c[i] == '\n') {
            ++count;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,当我尝试读取文件(CSV,Syslog或任何其他野生格式)时,它运行得很好,并给我正确的结果.但是当我尝试运行一个通过mac生成的文件时,它会变成干线,只是报告回读了一行.

现在我的日志文件很大,我知道它有几千行日志,但它只读了一行.我在Sublime中打开了这个文件,我可以看到所有单独的行,但是当我通过VIM查看这个文件时,它只显示了一个文件,每行末尾有一个字符'^ M'(我猜它是正在使用它作为行终止符).

两行的样本如下.你可以看到vim正在显示它应该是新行的^ M字符

15122,25Dec2013,19:42:25,192.168.5.1,log,allow ,, eth0,outbound,Application Control ,, Network,Bob(+),Bob(+),,,, 59857d77 ,,,,,,,, 570033 ,,,,,,,,,,,,, 192.168.5.7,176.32.96.190,tcp,80,56305,15606,554427,60461741,** ,,,,,,,, 1,**,**,**,**,**,**,**,**,**,其他:Wget/1.13.4(linux-gnu),其他:服务器,192.168.5.7,60461741:1 ,,,,, ,**,**,** ,,, ** ,,,, ^ M359,23Dec2013,18:54:03,192.168.5.1,log,allow ,, eth0,outbound,Application Control ,, Network,Charlie(+)查理(+),,,, c0fa2dac ,,,,,,,, 1171362 ,,,,,,,,,,,,, 192.168.5.6,205.251.242.54,TCP,80,45483,31395,1139967, 60340847,** ,,,,,,, 2,**,**,**,**,**,**,**,**,**,其他:Wget/1.13.4(linux- gnu),其他:服务器,192.168.5.6,60340847:1 ,,,,,,, **,**,** ,,, ** ,,,, ^ M

有关如何解决这个问题的任何建议?

Jon*_*eet 5

甚至在你到达换行符之前的第一个问题是你正在读取字节然后将它们视为字符.您实际上正在假设ISO-8859-1的编码可能不正确.你应该使用一个InputStreamReader代替.

然后是操作系统具有不同换行符的问题...用于BufferedReader.readLine()以处理换行符的方式读取一行\n,\r或者\r\n.

所以你的代码将成为:

int count = 0;
try (BufferedReader reader = new BufferedReader(
     new InputStreamReader(is, charset))) {
   while (reader.readLine() != null) {
       count++;
   }
}
Run Code Online (Sandbox Code Playgroud)