Java IO 字节流计数问题

[code="java"]
long count = 0;
String line = br.readLine();
while (line != null) {
if (count > length) {
break;
}

                count += line.getBytes("UTF-8").length;
                count += 1; // Add \r's length
                System.out.println(Thread.currentThread() + "  " + line);
                System.out.println(" count:" + count);
                line = br.readLine();
            }

[/code]

用这样的方法来统计已读的字节数为什么输出的结果不对呢?具体的说count统计的数目比实际的要少,这是什么原因造成的?

[code="java"]File file = new File("D:\todo.txt");
BufferedReader br = new BufferedReader(new FileReader(file));
long length = 1261192704;
long count = 0;
String line = br.readLine();
while (line != null) {
if (count > length) {
break;
}
count += 2;
count += line.getBytes("utf-8").length;
System.out.println(line);
line = br.readLine();
}

    System.out.println(count);
    FileInputStream fis = new FileInputStream(file);
    System.out.println(fis.available());[/code]

测试结果:
1、如果windows上边读windows文件 返回结果是正确的;
2、如果windows上边读linux文件结果是有偏差的(count += 1)。

[quote]getBytes
public byte[] getBytes(Charset charset)使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。
此方法总是使用此字符集的默认替代 byte 数组替代错误输入和不可映射字符序列。如果需要对编码过程进行更多控制,则应该使用 CharsetEncoder 类。
[/quote]

难道有些linux字符在windows上无法映射? 你试下 在linux上读取linux文件 结果对吗

要考虑 换行符 在window上边 是\r\n(两个字节) 在linux上是\r(一个);

count += 1; // Add \r's length 这个不用要了吧,已经作了line != null的判断了 应该会排除掉空的回车。每次读一行就用count += 1;好像是错误的。

if (count > length) {

break;

}

这个判断感觉也好别扭。不知道是什么 可能也会影响结果 都非空判断了 不用break了吧 count>length是判断什么的?

问题找到了,
Reader 在读取字符时,在linux上你是把换行符当作一个字节看待,但是如果我忘文件里写了\r\n 你也是看作一个的(就是说linux上也可能写\r\n 可是你只记录了1个字节),所以出问题了。
[code="java"]
FileInputStream fis = new FileInputStream(file);
System.out.println(fis.available());

    long r = 0;
    long n = 0;
    long c = 0;
    int i = fis.read(); 
    while(i != -1) {
        if(i == '\r') {
            r++;
        }
        if(i == '\n') {
            n++;
        }

        c++;
        i = fis.read();
    }
    System.out.println(c);
    System.out.println(r);
    System.out.println(n);

[/code]

:oops: 第二行的 String line = br.readLine(); 经读了一些字符了,但是此时count = 0。。。所以你的程序应该少了第二行程序读到的字符数。

按照byte流读取..不要按照read流读取