简体   繁体   English

BufferedReader不读取文件中的所有行

[英]BufferedReader doesn't read all lines from file

I am trying to read /proc/net/xt_qtaguid/stats in Android 6. 我试图在Android 6中读取/proc/net/xt_qtaguid/stats
Using cat command, I get this: 使用cat命令,我得到这个:

2 a0 0 0 123456 311 48329 737 48 1
3 b0 0 0 0 0 0 0 0
4 c0 123456 311 48329 737 48 1
5 d0 111111 111 22222 222 33 1

My java code tries to read the file line by line: 我的java代码尝试逐行读取文件:

File sysDataFile = new File(PATH_TO_FILE);
BufferedReader bufReader = null;
FileReader fileReader = null;
try {
   fileReader = new FileReader(sysDataFile);
   bufReader = new BufferedReader(fileReader);

   String line = null;
   while ((line = bufferedReader.readLine()) != null) {
       // print to console each line
       System.out.println("Line: " + line);
   }
 } catch (IOException e) {
    System.out.println("IOException thrown!");           
 } finally {
   bufReader.close();
   fileReader.close();
 }

When I run the above code, it only print out the first two lines in console: 当我运行上面的代码时,它只打印出控制台中的前两行:

Line: 2 a0 0 0 123456 311 48329 737 48 1
Line: 3 b0 0 0 0 0 0 0 0

Why? 为什么?

I am trying to read /proc/net/xt_qtaguid/stats in Android 6. 我试图在Android 6中读取/proc/net/xt_qtaguid/stats

In Linux, files under /proc/ are not actually files: they are handled by procfs , a special filesystem that executes code each time the file entry is read or written (code being a callback function defined in a kernel module). 在Linux中, /proc/下的文件实际上不是文件:它们由procfs处理, procfs是一个特殊的文件系统, 每次读取或写入文件条目时都执行代码 (代码是内核模块中定义的回调函数)。 So those pseudo-files are not static like regular files, but completely dynamic . 所以这些伪文件不像常规文件那样是静态的,而是完全动态的 The size gives an interesting clue: (most of) those files have a length of 0 (as can be seen with ls -l ), but when read they show some content. 大小提供了一个有趣的线索:(大部分) 这些文件的长度为0 (如ls -l ),但在阅读时它们会显示一些内容。

In short, it is to be expected that reading that same file from 2 different contexts yields 2 different results. 简而言之,可以预期从2个不同的上下文中读取相同的文件会产生2个不同的结果。

In this instance, the "file" callbacks are handled by xt_qtaguid module for Android , which manages "per-application/delegated data usage monitoring". 在这种情况下,“文件”回调由Androidxt_qtaguid模块处理, xt_qtaguid模块管理“每个应用程序/委托数据使用监视”。

This answer says: 这个答案说:

this virtual file's read_proc function limit the uid, every application can only read the header and its own line. 这个虚拟文件的read_proc函数限制了uid,每个应用程序只能读取标题和自己的行。

The first part is a bit vague but seems to indicate the difference is based on user id, and the module will only "print" 2 lines of data when a regular application reads this file (please note Android assigns a unique user ID to each application and runs it as that user in a separate process ). 第一部分有点模糊,但似乎表明差异是基于用户ID,并且模块只会在常规应用程序读取此文件时“打印”2行数据(请注意Android为每个应用程序分配唯一的用户ID并在单独的进程中以该用户身份运行它 )。

You don't give enough details but I have to assume that when you print it from adb using cat , you probably don't have the same user id and permissions as when you try to read it from your application. 您没有提供足够的详细信息,但我必须假设当您使用cat从adb打印它时,您可能没有与尝试从应用程序中读取它时相同的用户ID和权限。 I did not track the exact implementation details (if you want to, the source for this module can be read here ), but other variables might come into play. 我没有跟踪确切的实现细节(如果你愿意, 可以在这里阅读这个模块的源代码 ),但其他变量可能会起作用。

The doc says : 医生说

In the case of applications that provide network data transfer as a service, such as the download manager, media streaming service, etc, it is possible to attribute the ownership of the network data transfer to the UID of the requesting application using the TrafficStats.setThreadStatsUid() function call. 对于提供网络数据传输作为服务的应用程序(例如下载管理器,媒体流服务等),可以使用TrafficStats.setThreadStatsUid()将网络数据传输的所有权归属于请求应用程序的UID。 TrafficStats.setThreadStatsUid()函数调用。 The caller must hold the android.permission.MODIFY_NETWORK_ACCOUNTING permission to re-assign the ownership of the network traffic. 调用者必须持有android.permission.MODIFY_NETWORK_ACCOUNTING权限才能重新分配网络流量的所有权。

So a process/application can use TrafficStats.setThreadStatsUid() in order to get more lines from that file, but that requires MODIFY_NETWORK_ACCOUNTING permission. 因此,进程/应用程序可以使用TrafficStats.setThreadStatsUid()以从该文件中获取更多行,但这需要MODIFY_NETWORK_ACCOUNTING权限。

Since performance is not an issue, the easiest and safest option would be to launch cat in a process from java redirect the standard output to an stream and read the contents in a reader. 由于性能不是问题,最简单和最安全的选择是在java中将cat标准输出重定向到流中并在读取器中读取内容。 Using this as guidance: Run cat command in Android 使用它作为指导: 在Android中运行cat命令

No need to modify permissions to provide a backtick 无需修改权限即可提供反引号

The readLine() method reads until the next '\\n' character. readLine()方法读取直到下一个'\\ n'字符。 Hypothetically, if you have two consecutive '\\n' characters, then readLine() could return null prematurely. 假设,如果你有两个连续的'\\ n'字符,那么readLine() 可能会过早地返回null。 However, if this was the case, then cat should have put an extra line in between those two lines. 但是,如果是这种情况,那么cat应该在这两行之间增加一条线。

At this point you can try two things: 此时你可以尝试两件事:

  1. check the charset your system file and your program use are the same 检查charset您的系统文件和您的程序使用是否相同
  2. change this: 改变这个:

     String line = null; while ((line = bufferedReader.readLine()) != null) { // print to console each line System.out.println("Line: " + line); } 

    to this: 对此:

     char c = null; while ((c = (char)bufferedReader.read()) != null) { // print to console each char System.out.println("Line: " + c); } 

and see what happens. 看看会发生什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM