IO流


* 查看FileOutputStream的构造方法:
*
* FileOutputStream(File file)
* FileOutputStream(String name)
*
* 字节输出流操作步骤:
* A:创建字节输出流对象
* B:写数据
* C:释放资源

 1         // 创建字节输出流对象
 2         // FileOutputStream(File file)
 3         // File file = new File("fos.txt");
 4         // FileOutputStream fos = new FileOutputStream(file);
 5         // FileOutputStream(String name)
 6         FileOutputStream fos = new FileOutputStream("fos.txt");
 7         /*
 8          * 创建字节输出流对象了做了几件事情:
 9          * A:调用系统功能去创建文件
10          * B:创建fos对象
11          * C:把fos对象指向这个文件
12          */
13         
14         //写数据
15         fos.write("hello,IO".getBytes());
16         fos.write("java".getBytes());
17         
18         //释放资源
19         //关闭此文件输出流并释放与此流有关的所有系统资源。
20         fos.close();
21         /*
22          * 为什么一定要close()呢?
23          * A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
24          * B:通知系统去释放跟该文件相关的资源
25          */
26         //java.io.IOException: Stream Closed
27         //fos.write("java".getBytes());

* 字节输出流操作步骤:
* A:创建字节输出流对象
* B:调用write()方法
* C:释放资源
*
* public void write(int b):写一个字节
* public void write(byte[] b):写一个字节数组
* public void write(byte[] b,int off,int len):写一个字节数组的一部分

 1         // 创建字节输出流对象
 2         // OutputStream os = new FileOutputStream("fos2.txt"); // 多态
 3         FileOutputStream fos = new FileOutputStream("fos2.txt");
 4 
 5         // 调用write()方法
 6         //fos.write(97); //97 -- 底层二进制数据    -- 通过记事本打开 -- 找97对应的字符值 -- a
 7         // fos.write(57);
 8         // fos.write(55);
 9         
10         //public void write(byte[] b):写一个字节数组
11         byte[] bys={97,98,99,100,101};
12         fos.write(bys);
13         
14         //public void write(byte[] b,int off,int len):写一个字节数组的一部分
15         fos.write(bys,1,3);
16         
17         //释放资源
18         fos.close();

* 如何实现数据的换行?
* 为什么现在没有换行呢?因为你值写了字节数据,并没有写入换行符号。
* 如何实现呢?写入换行符号即可呗。
* 刚才我们看到了有写文本文件打开是可以的,通过windows自带的那个不行,为什么呢?
* 因为不同的系统针对不同的换行符号识别是不一样的?
* windows:
* linux:
* Mac:
* 而一些常见的个高级记事本,是可以识别任意换行符号的。
*
* 如何实现数据的追加写入?
* 用构造方法带第二个参数是true的情况即可

 1         // 创建字节输出流对象
 2         // FileOutputStream fos = new FileOutputStream("fos3.txt");
 3         // 创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。
 4         FileOutputStream fos = new FileOutputStream("fos3.txt", true);
 5 
 6         // 写数据
 7         for (int x = 0; x < 10; x++) {
 8             fos.write(("hello" + x).getBytes());
 9             fos.write("
".getBytes());
10         }
11 
12         // 释放资源
13         fos.close();

FileOutPutStream写出数据加入异常处理:

 1         // 改进版
 2         // 为了在finally里面能够看到该对象就必须定义到外面,为了访问不出问题,还必须给初始化值
 3         FileOutputStream fos = null;
 4         try {
 5             // fos = new FileOutputStream("z:\fos4.txt");
 6             fos = new FileOutputStream("fos4.txt");
 7             fos.write("java".getBytes());
 8         } catch (FileNotFoundException e) {
 9             e.printStackTrace();
10         } catch (IOException e) {
11             e.printStackTrace();
12         } finally {
13             // 如果fos不是null,才需要close()
14             if (fos != null) {
15                 // 为了保证close()一定会执行,就放到这里了
16                 try {
17                     fos.close();
18                 } catch (IOException e) {
19                     e.printStackTrace();
20                 }
21             }
22         }

* 字节输入流操作步骤:
* A:创建字节输入流对象
* B:调用read()方法读取数据,并把数据显示在控制台
* C:释放资源
*
* 读取数据的方式:
* A:int read():一次读取一个字节
* B:int read(byte[] b):一次读取一个字节数组

 1         FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
 2 
 3         // 最终版代码
 4         int by = 0;
 5         // 读取,赋值,判断
 6         while ((by = fis.read()) != -1) {
 7             System.out.print((char) by);
 8         }
 9 
10         // 释放资源
11         fis.close();

* 一次读取一个字节数组:int read(byte[] b)
* 返回值其实是实际读取的字节个数。

 1         // 创建字节输入流对象
 2         FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java");
 3 
 4         // 最终版代码
 5         // 数组的长度一般是1024或者1024的整数倍
 6         byte[] bys = new byte[1024];
 7         int len = 0;
 8         while ((len = fis.read(bys)) != -1) {
 9             System.out.print(new String(bys, 0, len));
10         }
11 
12         // 释放资源
13         fis.close();

* 计算机是如何识别什么时候该把两个字节转换为一个中文呢?
* 在计算机中中文的存储分两个字节:
* 第一个字节肯定是负数。
* 第二个字节常见的是负数,可能有正数。但是没影响。

1         String s = "我爱你中国";
2         // [-50, -46, -80, -82, -60, -29, -42, -48, -71, -6]
3 
4         byte[] bys = s.getBytes();
5         System.out.println(Arrays.toString(bys));

* 通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。
* 既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。
* 这种类被称为:缓冲区类(高效类)
* 写数据:BufferedOutputStream
* 读数据:BufferedInputStream
*
* 构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。
*
* 为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
* 原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现。

 1         // BufferedInputStream(InputStream in)
 2         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
 3                 "bos.txt"));
 4 
 5         // 读取数据
 6         byte[] bys = new byte[1024];
 7         int len = 0;
 8         while ((len = bis.read(bys)) != -1) {
 9             System.out.print(new String(bys, 0, len));
10         }
11 
12         // 释放资源
13         bis.close();
1         BufferedOutputStream bos = new BufferedOutputStream(
2                 new FileOutputStream("bos.txt"));
3 
4         // 写数据
5         bos.write("hello".getBytes());
6 
7         // 释放资源
8         bos.close();

* 字节流四种方式复制文件:
* 基本字节流一次读写一个字节: 共耗时:117235毫秒
* 基本字节流一次读写一个字节数组: 共耗时:156毫秒
* 高效字节流一次读写一个字节: 共耗时:1141毫秒
* 高效字节流一次读写一个字节数组: 共耗时:47毫秒

 1     public static void main(String[] args) throws IOException {
 2         long start = System.currentTimeMillis();
 3         // method1("e:\哥有老婆.mp4", "copy1.mp4");
 4         // method2("e:\哥有老婆.mp4", "copy2.mp4");
 5         // method3("e:\哥有老婆.mp4", "copy3.mp4");
 6         method4("e:\哥有老婆.mp4", "copy4.mp4");
 7         long end = System.currentTimeMillis();
 8         System.out.println("共耗时:" + (end - start) + "毫秒");
 9     }
10 
11     // 高效字节流一次读写一个字节数组:
12     public static void method4(String srcString, String destString)
13             throws IOException {
14         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
15                 srcString));
16         BufferedOutputStream bos = new BufferedOutputStream(
17                 new FileOutputStream(destString));
18 
19         byte[] bys = new byte[1024];
20         int len = 0;
21         while ((len = bis.read(bys)) != -1) {
22             bos.write(bys, 0, len);
23         }
24 
25         bos.close();
26         bis.close();
27     }
28 
29     // 高效字节流一次读写一个字节:
30     public static void method3(String srcString, String destString)
31             throws IOException {
32         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
33                 srcString));
34         BufferedOutputStream bos = new BufferedOutputStream(
35                 new FileOutputStream(destString));
36 
37         int by = 0;
38         while ((by = bis.read()) != -1) {
39             bos.write(by);
40 
41         }
42 
43         bos.close();
44         bis.close();
45     }
46 
47     // 基本字节流一次读写一个字节数组
48     public static void method2(String srcString, String destString)
49             throws IOException {
50         FileInputStream fis = new FileInputStream(srcString);
51         FileOutputStream fos = new FileOutputStream(destString);
52 
53         byte[] bys = new byte[1024];
54         int len = 0;
55         while ((len = fis.read(bys)) != -1) {
56             fos.write(bys, 0, len);
57         }
58 
59         fos.close();
60         fis.close();
61     }
62 
63     // 基本字节流一次读写一个字节
64     public static void method1(String srcString, String destString)
65             throws IOException {
66         FileInputStream fis = new FileInputStream(srcString);
67         FileOutputStream fos = new FileOutputStream(destString);
68 
69         int by = 0;
70         while ((by = fis.read()) != -1) {
71             fos.write(by);
72         }
73 
74         fos.close();
75         fis.close();
76     }

* 复制文本文件
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字符流更方便一些。
* 而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。
* 数据源:
* c:\a.txt -- FileReader -- BufferdReader
* 目的地:
* d:\b.txt -- FileWriter -- BufferedWriter

 1     // 字符缓冲流一次读写一个字符串
 2     private static void method5(String srcString, String destString)
 3             throws IOException {
 4         BufferedReader br = new BufferedReader(new FileReader(srcString));
 5         BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
 6 
 7         String line = null;
 8         while ((line = br.readLine()) != null) {
 9             bw.write(line);
10             bw.newLine();
11             bw.flush();
12         }
13 
14         bw.close();
15         br.close();
16     }
17 
18     // 字符缓冲流一次读写一个字符数组
19     private static void method4(String srcString, String destString)
20             throws IOException {
21         BufferedReader br = new BufferedReader(new FileReader(srcString));
22         BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
23 
24         char[] chs = new char[1024];
25         int len = 0;
26         while ((len = br.read(chs)) != -1) {
27             bw.write(chs, 0, len);
28         }
29 
30         bw.close();
31         br.close();
32     }
33 
34     // 字符缓冲流一次读写一个字符
35     private static void method3(String srcString, String destString)
36             throws IOException {
37         BufferedReader br = new BufferedReader(new FileReader(srcString));
38         BufferedWriter bw = new BufferedWriter(new FileWriter(destString));
39 
40         int ch = 0;
41         while ((ch = br.read()) != -1) {
42             bw.write(ch);
43         }
44 
45         bw.close();
46         br.close();
47     }
48 
49     // 基本字符流一次读写一个字符数组
50     private static void method2(String srcString, String destString)
51             throws IOException {
52         FileReader fr = new FileReader(srcString);
53         FileWriter fw = new FileWriter(destString);
54 
55         char[] chs = new char[1024];
56         int len = 0;
57         while ((len = fr.read(chs)) != -1) {
58             fw.write(chs, 0, len);
59         }
60 
61         fw.close();
62         fr.close();
63     }
64 
65     // 基本字符流一次读写一个字符
66     private static void method1(String srcString, String destString)
67             throws IOException {
68         FileReader fr = new FileReader(srcString);
69         FileWriter fw = new FileWriter(destString);
70 
71         int ch = 0;
72         while ((ch = fr.read()) != -1) {
73             fw.write(ch);
74         }
75 
76         fw.close();
77         fr.close();
78     }

* 复制图片
*
* 分析:
* 复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。
* 通过该原理,我们知道我们应该采用字节流。
* 而字节流有4种方式,所以做这个题目我们有4种方式。推荐掌握第4种。
*
* 数据源:
* c:\a.jpg -- FileInputStream -- BufferedInputStream
* 目的地:
* d:\b.jpg -- FileOutputStream -- BufferedOutputStream

 1     // 字节缓冲流一次读写一个字节数组
 2     private static void method4(File srcFile, File destFile) throws IOException {
 3         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
 4                 srcFile));
 5         BufferedOutputStream bos = new BufferedOutputStream(
 6                 new FileOutputStream(destFile));
 7 
 8         byte[] bys = new byte[1024];
 9         int len = 0;
10         while ((len = bis.read(bys)) != -1) {
11             bos.write(bys, 0, len);
12         }
13 
14         bos.close();
15         bis.close();
16     }
17 
18     // 字节缓冲流一次读写一个字节
19     private static void method3(File srcFile, File destFile) throws IOException {
20         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
21                 srcFile));
22         BufferedOutputStream bos = new BufferedOutputStream(
23                 new FileOutputStream(destFile));
24 
25         int by = 0;
26         while ((by = bis.read()) != -1) {
27             bos.write(by);
28         }
29 
30         bos.close();
31         bis.close();
32     }
33 
34     // 基本字节流一次读写一个字节数组
35     private static void method2(File srcFile, File destFile) throws IOException {
36         FileInputStream fis = new FileInputStream(srcFile);
37         FileOutputStream fos = new FileOutputStream(destFile);
38 
39         byte[] bys = new byte[1024];
40         int len = 0;
41         while ((len = fis.read(bys)) != -1) {
42             fos.write(bys, 0, len);
43         }
44 
45         fos.close();
46         fis.close();
47     }
48 
49     // 基本字节流一次读写一个字节
50     private static void method1(File srcFile, File destFile) throws IOException {
51         FileInputStream fis = new FileInputStream(srcFile);
52         FileOutputStream fos = new FileOutputStream(destFile);
53 
54         int by = 0;
55         while ((by = fis.read()) != -1) {
56             fos.write(by);
57         }
58 
59         fos.close();
60         fis.close();
61     }

 * 需求:把ArrayList集合中的字符串数据存储到文本文件

 1         // 封装数据与(创建集合对象)
 2         ArrayList<String> array = new ArrayList<String>();
 3         array.add("hello");
 4         array.add("world");
 5         array.add("java");
 6 
 7         // 封装目的地
 8         BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
 9 
10         // 遍历集合
11         for (String s : array) {
12             // 写数据
13             bw.write(s);
14             bw.newLine();
15             bw.flush();
16         }
17 
18         // 释放资源
19         bw.close();

 * 需求:从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合

 1         // 封装数据源
 2         BufferedReader br = new BufferedReader(new FileReader("b.txt"));
 3         // 封装目的地(创建集合对象)
 4         ArrayList<String> array = new ArrayList<String>();
 5 
 6         // 读取数据存储到集合中
 7         String line = null;
 8         while ((line = br.readLine()) != null) {
 9             array.add(line);
10         }
11 
12         // 释放资源
13         br.close();
14 
15         // 遍历集合
16         for (String s : array) {
17             System.out.println(s);
18         }

* 需求:复制指定目录下的指定文件,并修改后缀名。
* 指定的文件是:.java文件。
* 指定的后缀名是:.jad
* 指定的目录是:jad

 1         // 封装目录
 2         File srcFolder = new File("e:\java");
 3         // 封装目的地
 4         File destFolder = new File("e:\jad");
 5         // 如果目的地目录不存在,就创建
 6         if (!destFolder.exists()) {
 7             destFolder.mkdir();
 8         }
 9 
10         // 获取该目录下的java文件的File数组
11         File[] fileArray = srcFolder.listFiles(new FilenameFilter() {
12             @Override
13             public boolean accept(File dir, String name) {
14                 return new File(dir, name).isFile() && name.endsWith(".java");
15             }
16         });
17 
18         // 遍历该File数组,得到每一个File对象
19         for (File file : fileArray) {
20             // System.out.println(file);
21             // 数据源:e:javaDataTypeDemo.java
22             // 目的地:e:\jadDataTypeDemo.java
23             String name = file.getName();
24             File newFile = new File(destFolder, name);
25             copyFile(file, newFile);
26         }
27 
28         // 在目的地目录下改名
29         File[] destFileArray = destFolder.listFiles();
30         for (File destFile : destFileArray) {
31             // System.out.println(destFile);
32             // e:jadDataTypeDemo.java
33             // e:\jad\DataTypeDemo.jad
34             String name =destFile.getName(); //DataTypeDemo.java
35             String newName = name.replace(".java", ".jad");//DataTypeDemo.jad
36             
37             File newFile = new File(destFolder,newName);
38             destFile.renameTo(newFile);
39         }
40     }
41 
42     private static void copyFile(File file, File newFile) throws IOException {
43         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
44                 file));
45         BufferedOutputStream bos = new BufferedOutputStream(
46                 new FileOutputStream(newFile));
47 
48         byte[] bys = new byte[1024];
49         int len = 0;
50         while ((len = bis.read(bys)) != -1) {
51             bos.write(bys, 0, len);
52         }
53 
54         bos.close();
55         bis.close();
56     }

 * 需求:复制多极文件夹

 1     public static void main(String[] args) throws IOException {
 2         // 封装数据源File
 3         File srcFile = new File("E:\JavaSE\day21\code\demos");
 4         // 封装目的地File
 5         File destFile = new File("E:\");
 6 
 7         // 复制文件夹的功能
 8         copyFolder(srcFile, destFile);
 9     }
10 
11     private static void copyFolder(File srcFile, File destFile)
12             throws IOException {
13         // 判断该File是文件夹还是文件
14         if (srcFile.isDirectory()) {
15             // 文件夹
16             File newFolder = new File(destFile, srcFile.getName());
17             newFolder.mkdir();
18 
19             // 获取该File对象下的所有文件或者文件夹File对象
20             File[] fileArray = srcFile.listFiles();
21             for (File file : fileArray) {
22                 copyFolder(file, newFolder);
23             }
24         } else {
25             // 文件
26             File newFile = new File(destFile, srcFile.getName());
27             copyFile(srcFile, newFile);
28         }
29     }
30 
31     private static void copyFile(File srcFile, File newFile) throws IOException {
32         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
33                 srcFile));
34         BufferedOutputStream bos = new BufferedOutputStream(
35                 new FileOutputStream(newFile));
36 
37         byte[] bys = new byte[1024];
38         int len = 0;
39         while ((len = bis.read(bys)) != -1) {
40             bos.write(bys, 0, len);
41         }
42 
43         bos.close();
44         bis.close();
45     }

* 键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件
*
* 分析:
* A:创建学生类
* B:创建集合对象
* TreeSet<Student>
* C:键盘录入学生信息存储到集合
* D:遍历集合,把数据写到文本文件

 1     public static void main(String[] args) throws IOException {
 2         // 创建集合对象
 3         TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
 4             @Override
 5             public int compare(Student s1, Student s2) {
 6                 int num = s2.getSum() - s1.getSum();
 7                 int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
 8                 int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
 9                 int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
10                 int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName())
11                         : num4;
12                 return num5;
13             }
14         });
15 
16         // 键盘录入学生信息存储到集合
17         for (int x = 1; x <= 5; x++) {
18             Scanner sc = new Scanner(System.in);
19             System.out.println("请录入第" + x + "个的学习信息");
20             System.out.println("姓名:");
21             String name = sc.nextLine();
22             System.out.println("语文成绩:");
23             int chinese = sc.nextInt();
24             System.out.println("数学成绩:");
25             int math = sc.nextInt();
26             System.out.println("英语成绩:");
27             int english = sc.nextInt();
28 
29             // 创建学生对象
30             Student s = new Student();
31             s.setName(name);
32             s.setChinese(chinese);
33             s.setMath(math);
34             s.setEnglish(english);
35 
36             // 把学生信息添加到集合
37             ts.add(s);
38         }
39 
40         // 遍历集合,把数据写到文本文件
41         BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"));
42         bw.write("学生信息如下:");
43         bw.newLine();
44         bw.flush();
45         bw.write("姓名,语文成绩,数学成绩,英语成绩");
46         bw.newLine();
47         bw.flush();
48         for (Student s : ts) {
49             StringBuilder sb = new StringBuilder();
50             sb.append(s.getName()).append(",").append(s.getChinese())
51                     .append(",").append(s.getMath()).append(",")
52                     .append(s.getEnglish());
53             bw.write(sb.toString());
54             bw.newLine();
55             bw.flush();
56         }
57         // 释放资源
58         bw.close();
59         System.out.println("学习信息存储完毕");
60     }

* 用Reader模拟BufferedReader的readLine()功能
*
* readLine():一次读取一行,根据换行符判断是否结束,只返回内容,不返回换行符

 1 public class MyBufferedReader {
 2     private Reader r;
 3 
 4     public MyBufferedReader(Reader r) {
 5         this.r = r;
 6     }
 7 
 8     /*
 9      * 思考:写一个方法,返回值是一个字符串。
10      */
11     public String readLine() throws IOException {
12         /*
13          * 我要返回一个字符串,我该怎么办呢? 我们必须去看看r对象能够读取什么东西呢? 两个读取方法,一次读取一个字符或者一次读取一个字符数组
14          * 那么,我们要返回一个字符串,用哪个方法比较好呢? 我们很容易想到字符数组比较好,但是问题来了,就是这个数组的长度是多长呢?
15          * 根本就没有办法定义数组的长度,你定义多长都不合适。 所以,只能选择一次读取一个字符。
16          * 但是呢,这种方式的时候,我们再读取下一个字符的时候,上一个字符就丢失了 所以,我们又应该定义一个临时存储空间把读取过的字符给存储起来。
17          * 这个用谁比较和是呢?数组,集合,字符串缓冲区三个可供选择。
18          * 经过简单的分析,最终选择使用字符串缓冲区对象。并且使用的是StringBuilder
19          */
20         StringBuilder sb = new StringBuilder();
21 
22         // 做这个读取最麻烦的是判断结束,但是在结束之前应该是一直读取,直到-1
23         
24         
25         /*
26         hello
27         world
28         java    
29         
30         104101108108111
31         119111114108100
32         1069711897
33          */
34         
35         int ch = 0;
36         while ((ch = r.read()) != -1) { //104,101,108,108,111
37             if (ch == '
') {
38                 continue;
39             }
40 
41             if (ch == '
') {
42                 return sb.toString(); //hello
43             } else {
44                 sb.append((char)ch); //hello
45             }
46         }
47 
48         // 为了防止数据丢失,判断sb的长度不能大于0.就是怕最后一行没有换行,那就没有换行符.
49         if (sb.length() > 0) {
50             return sb.toString();
51         }
52 
53         return null;
54     }
55 
56     /*
57      * 先写一个关闭方法
58      */
59     public void close() throws IOException {
60         this.r.close();
61     }
62 }

* 测试MyBufferedReader的时候,你就把它当作BufferedReader一样的使用

 1 public class MyBufferedReaderDemo {
 2     public static void main(String[] args) throws IOException {
 3         MyBufferedReader mbr = new MyBufferedReader(new FileReader("my.txt"));
 4 
 5         String line = null;
 6         while ((line = mbr.readLine()) != null) {
 7             System.out.println(line);
 8         }
 9 
10         mbr.close();
11     }
12 }

* BufferedReader
*   |--LineNumberReader
*      public int getLineNumber()获得当前行号。
*      public void setLineNumber(int lineNumber)

 1         LineNumberReader lnr = new LineNumberReader(new FileReader("my.txt"));
 2 
 3         // 从10开始才比较好
 4         // lnr.setLineNumber(10);
 5 
 6         // System.out.println(lnr.getLineNumber());
 7         // System.out.println(lnr.getLineNumber());
 8         // System.out.println(lnr.getLineNumber());
 9 
10         String line = null;
11         while ((line = lnr.readLine()) != null) {
12             System.out.println(lnr.getLineNumber() + ":" + line);
13         }
14 
15         lnr.close();

自定义LineNumberReader:

 1 public class MyLineNumberReader {
 2     private Reader r;
 3     private int lineNumber = 0;
 4 
 5     public MyLineNumberReader(Reader r) {
 6         this.r = r;
 7     }
 8 
 9     public int getLineNumber() {
10         // lineNumber++;
11         return lineNumber;
12     }
13 
14     public void setLineNumber(int lineNumber) {
15         this.lineNumber = lineNumber;
16     }
17 
18     public String readLine() throws IOException {
19         lineNumber++;
20 
21         StringBuilder sb = new StringBuilder();
22 
23         int ch = 0;
24         while ((ch = r.read()) != -1) {
25             if (ch == '
') {
26                 continue;
27             }
28 
29             if (ch == '
') {
30                 return sb.toString();
31             } else {
32                 sb.append((char) ch);
33             }
34         }
35 
36         if (sb.length() > 0) {
37             return sb.toString();
38         }
39 
40         return null;
41     }
42 
43     public void close() throws IOException {
44         this.r.close();
45     }
46 }

或者:

 1 public class MyLineNumberReader2 extends MyBufferedReader {
 2     private Reader r;
 3 
 4     private int lineNumber = 0;
 5 
 6     public MyLineNumberReader2(Reader r) {
 7         super(r);
 8     }
 9 
10     public int getLineNumber() {
11         return lineNumber;
12     }
13 
14     public void setLineNumber(int lineNumber) {
15         this.lineNumber = lineNumber;
16     }
17 
18     @Override
19     public String readLine() throws IOException {
20         lineNumber++;
21         return super.readLine();
22     }
23 }
原文地址:https://www.cnblogs.com/samuraihuang/p/9905430.html