第15章.输入/输出

Posted lanshanxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第15章.输入/输出相关的知识,希望对你有一定的参考价值。

File类:

  访问文件和目录:

    File类可以使用文件路径字符串来创建File实例,该文件路径字符串既可以是绝对路径,也可以是相对路径。默认情况下,系统总是依据用户的工作路径来解释相对路径,这

     个路径由系统属性“user.dir”指定,通常也就是运行Java虚拟机时所在的路径。

    File类提供了很多方法来操作文件和目录:

      访问文件名相关的方法:

      1.String getName():返回此File对象所表示的文件名或路径名(若是路径,则返回最后一级子路径名)。

      2.String getPath():返回次File对象所对应的路径名

      3.File getAbsoluteFile():返回此File对象的绝对路径

      4.String getAbsolutePath():返回此File对象所对应的绝对路径名。

      5.String getParent():返回此File对象所对应目录(最后一级子目录)的父目录名

      6.boolean renameTo(File newName):重命名此File对象所对应的文件或目录,若重命名成功,则返回true,否则返回false

      文件检测相关的方法:

      1.boolean exists():判断File对象所对应的文件或目录是否存在

      2.boolean canWrite():判断File对象所对应的文件和目录是否可写

      3.boolean canRead():判断File对象所对应的文件和目录是否可读

      4.boolean isFile():判断File对象所对应的是否是文件,而不是目录

      5.boolean isDirectory():判断File对象所对应的是否是目录,而不是文件

      6.boolean isAbsolute():判断File对象所对应的文件或目录是否是绝对路径。该方法消除了不同平台的差异,可直接判断File对象是否为绝对路径。

      获取常规文件信息:

      1.long lastModified():返回文件的最后修改时间

      2.long length():返回文件内容的长度

      文件操作相关的方法:

      1.boolean createNewFile():当此File对象所对应的文件不存在时,该方法将新建一个该File对象所指定的新文件,若创建成功返回true,否则返回false

      2.boolean delete():删除File对象所对应的文件或路径

      3.static File createTempFile(String prefix, String suffix):在默认的临时文件目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定后缀作为文件名。

       File类可以直接调用该方法,prefix参数必须至少3字节长。建议前缀使用一个短的、有意义的字符串,如:hjb、mail。suffix参数可以为null,使用默认的后缀.tmp

      4.static File createTempFIle(String prefix, String suffix, File directory):在directory所指定的目录中创建一个临时的空文件,使用给定前缀、系统生成的随机数和给定

       后缀作为文件名。

      5.void deleteOnExit():注册一个删除钩子,指定当Java虚拟机退出时,删除File对象所对应的文件和目录

      目录操作相关的方法:

      1.boolean mkdir():创建一个File对象所对应的目录,若创建成功,则返回true,否则返回false。调用该方法时File对象必须对应一个路径,而不是一个文件。

      2.String[] list():列出File对象的所有子文件名和路径,返回String[]数组

      3.File[] listFiles():列出File对象的所有子文件和路径,返回Flie数组

      4.static File[] listRoots():列出系统所有的根路径

下面程序以几个简单的方法来测试以下File类的功能:

 1 import java.io.*;
 2 /**
 3  * Description:
 4  * <br/>网站: <a href="http://www.crazyit.org">疯狂Java联盟</a>
 5  * <br/>Copyright (C), 2001-2016, Yeeku.H.Lee
 6  * <br/>This program is protected by copyright laws.
 7  * <br/>Program Name:
 8  * <br/>Date:
 9  * @author Yeeku.H.Lee kongyeeku@163.com
10  * @version 1.0
11  */
12 public class FileTest
13 {
14     public static void main(String[] args)
15         throws IOException
16     {
17         // 以当前路径来创建一个File对象
18         File file = new File(".");
19         // 直接获取文件名,输出一点
20         System.out.println(file.getName());
21         // 获取相对路径的父路径可能出错,下面代码输出null
22         System.out.println(file.getParent());
23         // 获取绝对路径
24         System.out.println(file.getAbsoluteFile());
25         // 获取上一级路径
26         System.out.println(file.getAbsoluteFile().getParent());
27         // 在当前路径下创建一个临时文件
28         File tmpFile = File.createTempFile("aaa", ".txt", file);
29         // 指定当JVM退出时删除该文件
30         tmpFile.deleteOnExit();
31         // 以系统当前时间作为新文件名来创建新文件
32         File newFile = new File(System.currentTimeMillis() + ".txt");
33         System.out.println("newFile对象是否存在:"    + newFile.exists());
34         // 以指定newFile对象来创建一个文件
35         newFile.createNewFile();
36         // 以newFile对象来创建一个目录,因为newFile已经存在,
37         // 所以下面方法返回false,即无法创建该目录
38         newFile.mkdir();
39         // 使用list()方法来列出当前路径下的所有文件和路径
40         String[] fileList = file.list();
41         System.out.println("====当前路径下所有文件和路径如下====");
42         for (String fileName : fileList)
43         {
44             System.out.println(fileName);
45         }
46         // listRoots()静态方法列出所有的磁盘根路径。
47         File[] roots = File.listRoots();
48         System.out.println("====系统所有根路径如下====");
49         for (File root : roots)
50         {
51             System.out.println(root);
52         }
53     }
54 }
View Code

// 以系统当前时间作为新文件名来创建新文件
File newFile = new File(System.currentTimeMillis() + ".txt");
System.out.println("newFile对象是否存在:" + newFile.exists());

上面程序中这两句不懂,为什么明明存在的一个文件,却返回一个false?

  文件过滤器:

    在File类的list方法中可以接受一个FilenameFilter参数,通过该参数可以只列出符合条件的文件。

    FilenameFilter接口里包含了一个accept(File dir, String name)方法,该方法依次对指定File的所有子目录或文件进行迭代,若该方法返回true,则list()方法会列出该子目录

     或文件:

 1 import java.io.File;
 2 
 3 public class FilenameFilterTest{
 4     public static void main(String[] args){
 5         File file = new File(".");
 6         //使用Lambda表达式(目标类型为FilenameFiler)实现文件过滤器
 7         //若文件名以.java结尾,或者文件对应一个路径,则返回true
 8         String[] nameList = file.list((dir, name) -> name.endsWith(".java") || new File(name).isDirectory());
 9         for(String name : nameList){
10             System.out.println(name);
11         }
12     }
13 }
View Code

   字节流和字符流:

 1 import java.io.FileInputStream;
 2 import java.io.IOException;
 3 
 4 public class FileInputStreamTest {
 5     public static void main(String[] args) throws IOException{
 6         //创建字节输入流
 7         FileInputStream fis = new FileInputStream("FileInputStreamTest.java");
 8         //创建一个长度为1024的“竹筒”
 9         byte[] bbuf = new byte[1024];
10         //用于保存实际读取的字节数
11         int hasRead = 0;
12         //使用循环来重复“取水”过程
13         while((hasRead = fis.read(bbuf)) > 0){
14             //取出“竹筒”中的水滴(字节),将字节数组换成字符串输入
15             System.out.print(new String(bbuf, 0, hasRead));
16         }
17         
18         //关闭文件输入流,放在finally块里更安全
19         fis.close();
20     }
21 }
View Code

  程序最后关闭文件输入流,程序里打开的文件IO资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显示关闭文件IO资源。也可用try语句自动关闭IO流:

 1 import java.io.FileReader;
 2 import java.io.IOException;
 3 
 4 public class FileReaderTest{
 5     public static void main(String[] args) throws IOException{
 6         try(
 7             //创建字符输入流
 8             FileReader fr = new FileReader("FileReaderTest.java");
 9         ){
10             //创建一个长度为32的“竹筒”
11             char[] cbuf = new char[32];
12             //用于保存实际读取的字符数
13             int hasRead = 0;
14             //使用循环来重复“取水”过程
15             while((hasRead = fr.read(cbuf)) > 0){
16                 //取出“竹筒”中的水滴(字符),将字符数组转换成字符串输入!
17                 System.out.print(new String(cbuf, 0, hasRead));
18             }
19         }catch(IOException ex){
20             ex.printStackTrace();
21         }
22     }
23 }
View Code

  InputStream和Reader还支持如下几个方法来移动记录指针:

    1.void mark(int readAheadLimit):在记录指针当前位置记录一个标记。

    2.boolean markSupported():判断此输入流是否支持mark()操作,即是否支持记录标记

    3.void reset():将此流的记录指针重新定位到上一次记录标记(mark)的位置

    4.long skip(long n):记录指针向前移动n个字节/字符

  OutputStream和Writer:

    OutputStream和Writer类提供如下方法:

    1.void write(int c):将指定的字节/字符输出到输出流中,其中c既可以代表字节,也可以代表字符

    2.void write(byte[] / char[] buf):将字节数组/字符数组中的数据输出到指定输出流中

    3.void write(byte[] / char[] buf, int off, int len):将字节数组/字符数组中从off位置开始,长度为len的字节/字符书粗到输出流中。

    Writer还提供以下两个方法:

    1.void write(String str):将str字符串里包含的字符串输出到指定输出流中

    2.void write(String str, int off, int len):将str字符串里从off位置开始,长度为len的字符输出到指定输出流中

 1 import java.io.FileInputStream;
 2 import java.io.FileOutputStream;
 3 import java.io.IOException;
 4 
 5 public class FileOutputStreamTest{
 6     public static void main(String[] args){
 7         try(
 8             //创建字节输入流
 9             FileInputStream fis = new FileInputStream("FileOutputStreamTest.java");
10             //创建字节输出流
11             FileOutputStream fos = new FileOutputStream("newFile.txt")
12         ){
13             byte[] bbuf = new byte[32];
14             int hasRead = 0;
15             //循环从输入流中取出数据
16             while((hasRead = fis.read(bbuf)) > 0){
17                 //每次读取一次,即写入文件输入流,读了多少,就写多少
18                 fos.write(bbuf, 0, hasRead);
19             }
20         }catch(IOException ioe){
21             ioe.printStackTrace();
22         }
23     }
24 }
View Code

    若希望直接输出字符串内容,则使用Writer会更好:

 1 import java.io.FileWriter;
 2 import java.io.IOException;
 3 
 4 public class FileWriterTest{
 5     public static void main(String[] args){
 6         try(
 7             FileWriter fw = new FileWriter("poem.txt")
 8         ){
 9             fw.write("锦瑟 - 李商隐 \\r\\n");
10             fw.write("锦瑟无端五十弦,一弦一柱思华年。 \\r\\n");
11             fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。 \\r\\n");
12             fw.write("沧海月明珠有泪,蓝田日暖玉生烟。 \\r\\n");
13             fw.write("此情可待成追忆,只是当时已惘然。 \\r\\n");
14         }catch(IOException ioe){
15             ioe.printStackTrace();
16         }
17     }
18 }
View Code

  处理流的用法:

    下面程序使用PrintStream处理刘来包装OutputStream,使用处理流后的输出流在输出时将更加方便:

 1 import java.io.FileOutputStream;
 2 import java.io.PrintStream;
 3 import java.io.IOException;
 4 
 5 public class PrintStreamTest{
 6     public static void main(String[] args){
 7         try(
 8             FileOutputStream fos = new FileOutputStream("test.txt");
 9             PrintStream ps = new PrintStream(fos)
10         ){
11             //使用PrintStream执行输出
12             ps.println("普通字符串");
13             //直接使用PrintStreamTest输出对象
14             ps.println(new PrintStreamTest());
15         }catch(IOException ioe){
16             ioe.printStackTrace();
17         }
18     }
19 }
View Code

 1 import java.io.StringReader;
 2 import java.io.IOException;
 3 import java.io.StringWriter;
 4 
 5 public class StringNodeTest
 6 {
 7     public static void main(String[] args)
 8     {
 9         String src = "从明天起,做一个幸福的人\\n"
10             + "喂马,劈柴,周游世界\\n"
11             + "从明天起,关心粮食和蔬菜\\n"
12             + "我有一所房子,面朝大海,春暖花开\\n"
13             + "从明天起,和每一个亲人通信\\n"
14             + "告诉他们我的幸福\\n";
15         char[] buffer = new char[32];
16         int hasRead = 0;
17         try(
18             StringReader sr = new StringReader(src))
19         {
20             // 采用循环读取的访问读取字符串
21             while((hasRead = sr.read(buffer)) > 0)
22             {
23                 System.out.print(new String(buffer ,0 , hasRead));
24             }
25         }
26         catch (IOException ioe)
27         {
28             ioe.printStackTrace();
29         }
30         try(
31             // 创建StringWriter时,实际上以一个StringBuffer作为输出节点
32             // 下面指定的20就是StringBuffer的初始长度
33             StringWriter sw = new StringWriter())
34         {
35             // 调用StringWriter的方法执行输出
36             sw.write("有一个美丽的新世界,\\n");
37             sw.write("她在远方等我,\\n");
38             sw.write("哪里有天真的孩子,\\n");
39             sw.write("还有姑娘的酒窝\\n");
40             System.out.println("----下面是sw的字符串节点里的内容----");
41             // 使用toString()方法返回StringWriter的字符串节点的内容
42             System.out.println(sw.toString());
43         }
44         catch (IOException ex)
45         {
46             ex.printStackTrace();
47         }
48     }
49 }
View Code

  转换流:

    两个转换流用于实现将字节流转换为字符流,其中InputStreamReader将字节输入流转换为字符输入流,OutputStreamWriter将字节输出流转换为字符输出流。

 1 import java.io.InputStreamReader;
 2 import java.io.BufferedReader;
 3 import java.io.IOException;
 4 
 5 public class KeyinTest
 6 {
 7     public static void main(String[] args)
 8     {
 9         try(
10             // 将Sytem.in对象转换成Reader对象
11             InputStreamReader reader = new InputStreamReader(System.in);
12             // 将普通Reader包装成BufferedReader
13             BufferedReader br = new BufferedReader(reader))
14         {
15             String line = null;
16             // 采用循环方式来一行一行的读取
17             while ((line = br.readLine()) != null)
18             {
19                 // 如果读取的字符串为"exit",程序退出
20                 if (line.equals("exit"))
21                 {
22                     System.exit(1);
23                 }
24                 // 打印读取的内容
25                 System.out.println("输入内容为:" + line);
26             }
27         }
28         catch (IOException ioe)
29         {
30             ioe.printStackTrace();
31         }
32     }
33 }
View Code

    由于BufferedReader具有一个readLine()方法,可以非常方便依次读入一行内容,所以经常把读取文本内容的输入流包装成BufferedReader,用来方便地读取输入流的文

     本内容

  推回输入流:

    PushbackInputStream和PushbackReader提供了如下三个方法:

      1.void unread(byte[] / char[] buf):将一个字节/字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容

      2.void unread(byte[] / char[] b, int off, int len):将一个字节/字符数组里从off开始,长度为len字节/字符的内容推回到推回缓冲区里,从而重复读取刚刚读取的内容

      3.void unread(int b):将一个字节/字符推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。

 1 import java.io.PushbackInputStream;
 2 import java.io.PushbackReader;
 3 import java.io.FileReader;
 4 import java.io.IOException;
 5 
 6 public class PushbackTest
 7 {
 8     public static void main(String[] args)
 9     {
10         try(
11             // 创建一个PushbackReader对象,指定推回缓冲区的长度为64
12             PushbackReader pr = new PushbackReader(new FileReader(
13                 "PushbackTest.java") , 64))
14         {
15             char[] buf = new char[32];
16             // 用以保存上次读取的字符串内容
17             String lastContent = "";
18             int hasRead = 0;
19             // 循环读取文件内容
20             while ((hasRead = pr.read(buf)) > 0)
21             {
22                 // 将读取的内容转换成字符串
23                 String content = new String(buf , 0 , hasRead);
24                 int targetIndex = 0;
25                 // 将上次读取的字符串和本次读取的字符串拼起来,
26                 // 查看是否包含目标字符串, 如果包含目标字符串
27                 if ((targetIndex = (lastContent + content)
28                     .indexOf("new PushbackReader")) > 0)
29                 {
30                     // 将本次内容和上次内容一起推回缓冲区
31                     pr.unread((lastContent + content).toCharArray());
32                     // 重新定义一个长度为targetIndex的char数组
33                     if(targetIndex > 32)
34                     {
35                         buf = new char[targetIndex];
36                     }
37                     // 再次读取指定长度的内容(就是目标字符串之前的内容)
38                     pr.read(buf , 0 , targetIndex);
39                     // 打印读取的内容
40                     System.out.print(new String(buf , 0 ,targetIndex));
41                     System.exit(0);
42                 }
43                 else
44                 {
45                     // 打印上次读取的内容
46                     System.out.print(lastContent);
47                     // 将本次内容设为上次读取的内容
48                     lastContent = content;
49                 }
50             }
51         }
52         catch (IOException ioe)
53         {
54             ioe.printStackTrace();
55         }
56     }
57 }
View Code

第3章-15.删除重复字符 (20分)

第15章 位运算

第4章-6.输出前 n 个Fibonacci数 (15分)

Python第4章-15 换硬币 (20分)

第3章-14.统计一行文本的单词个数 (15分)

C Primer Plus第6版_源代码+练习答案