java基础学习_IO流04_用户登录注册案例(IO版)、数据操作流(操作基本数据类型的流)、内存操作流、打印流、标准输入输出流、随机访问流、合并流、序列化流(对象操作流)、Properties属性集合类、NIO(新IO)_day22总结
============================================================================= ============================================================================= 涉及到的知识点有:
1:用户登录注册案例(IO版) 2:数据操作流(操作基本数据类型的流)(理解) 3:内存操作流(理解) 4:打印流(掌握) 5:标准输入输出流(理解) 6:随机访问流(理解) 7:合并流(理解) 8:序列化流(对象操作流)(理解) 9:Properties属性集合类(理解) (1)Properties类的概述 (2)Properties类的特有功能 (3)Properties和IO流的结合使用 (4)案例 10:NIO(新IO)(了解) ============================================================================= ============================================================================= 1:用户登录注册案例(IO版) 要求,对着写一遍。 cn.itcast.pojo(用户层) User.java cn.itcast.dao(接口层) UserDao.java cn.itcast.dao.impl(接口实现层)只需要更改具体实现即可! UserDaoImpl.java cn.itcast.game(扩展曾) GuessNumber.java cn.itcast.test(测试层) UserTest.java
1 package cn.itcast.pojo; 2 3 /** 4 * 这是用户基本描述类 5 * 6 * @author 风清扬 7 * @version V1.1 8 * 9 */ 10 public class User { 11 // 用户名 12 private String username; 13 // 密码 14 private String password; 15 16 public User() { 17 } 18 19 public String getUsername() { 20 return username; 21 } 22 23 public void setUsername(String username) { 24 this.username = username; 25 } 26 27 public String getPassword() { 28 return password; 29 } 30 31 public void setPassword(String password) { 32 this.password = password; 33 } 34 }
1 package cn.itcast.dao; 2 3 import cn.itcast.pojo.User; 4 5 /** 6 * 这是针对用户进行操作的接口 7 * 8 * @author 风清扬 9 * @version V1.1 10 * 11 */ 12 public interface UserDao { 13 /** 14 * 这是用户登录功能 15 * 16 * @param username 17 * 用户名 18 * @param password 19 * 密码 20 * @return 返回登录是否成功 21 */ 22 public abstract boolean isLogin(String username, String password); 23 24 /** 25 * 这是用户注册功能 26 * 27 * @param user 28 * 要注册的用户信息 29 */ 30 public abstract void regist(User user); 31 }
1 package cn.itcast.dao.impl; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileNotFoundException; 7 import java.io.FileReader; 8 import java.io.FileWriter; 9 import java.io.IOException; 10 11 import cn.itcast.dao.UserDao; 12 import cn.itcast.pojo.User; 13 14 /** 15 * 这是用户操作的具体实现类(IO版) 16 * 17 * @author 风清扬 18 * @version V1.1 19 * 20 */ 21 public class UserDaoImpl implements UserDao { 22 // 创建文件前先要有一个新的文件路径名的抽象表示 23 private static File file = new File("user.txt"); 24 25 // 为了保证程序一启动,代码一加载,File对象就创建。使用静态代码块! 26 // 静态代码块只执行一次,随着类的加载而执行 27 static { 28 try { 29 file.createNewFile(); // File类的功能:public boolean createNewFile() 创建文件,如果存在这样的文件,就不创建了,返回false(该方法会抛异常) 30 } catch (IOException e) { 31 // e.printStackTrace(); 32 System.out.println("创建文件失败"); 33 } 34 } 35 36 // 登录相当于读取数据 37 @Override 38 public boolean isLogin(String username, String password) { 39 boolean flag = false; // 定义一个标记 40 41 BufferedReader br = null; 42 try { 43 // br = new BufferedReader(new FileReader("user.txt")); // 读取数据时,如果文件不存在,会抛出文件找不到异常。 44 br = new BufferedReader(new FileReader(file)); 45 46 String line = null; 47 while ((line = br.readLine()) != null) { 48 // 自定义的规则:用户名=密码 49 String[] datas = line.split("="); // 根据给定正则表达式的匹配拆分此字符串 50 if (datas[0].equals(username) && datas[1].equals(password)) { 51 flag = true; 52 break; 53 } 54 } 55 } catch (FileNotFoundException e) { 56 // e.printStackTrace(); 57 System.out.println("用户登录找不到信息所在的文件"); 58 } catch (IOException e) { 59 // e.printStackTrace(); 60 System.out.println("用户登录失败"); 61 } finally { 62 if (br != null) { 63 try { 64 br.close(); 65 } catch (IOException e) { 66 // e.printStackTrace(); 67 System.out.println("用户登录释放资源失败"); 68 } 69 } 70 } 71 72 return flag; 73 } 74 75 // 注册相当于写数据 76 @Override 77 public void regist(User user) { 78 /* 79 * 为了让注册的数据能够有一定的规则,我就自己定义了一个规则: 用户名=密码 80 * 即我把注册得到的数据提取出来,自定义拼接。 81 */ 82 83 // 1.不能把异常throws抛出到方法声明上,因为你的父类没有抛出异常。 84 // 2.又因为你抛出的是编译时期的异常,测试类调用该方法的时候,就需要处理该该异常,需要修改。但是测试代码我们一般是不需要修改的! 85 // 所以这次我们使用try...catch... 86 BufferedWriter bw = null; 87 try { 88 // bw = new BufferedWriter(new FileWriter("user.txt")); // 写数据时,如果文件不存在,会帮你创建文件,不会抛出异常。 89 // bw = new BufferedWriter(new FileWriter(file)); 90 // 为了保证数据是追加写入file里面的,必须加true 91 bw = new BufferedWriter(new FileWriter(file, true)); 92 bw.write(user.getUsername() + "=" + user.getPassword()); 93 bw.newLine(); 94 bw.flush(); 95 } catch (IOException e) { 96 // e.printStackTrace(); 97 System.out.println("用户注册失败"); 98 } finally { 99 if (bw != null) { 100 try { 101 bw.close(); // 关闭流操作一般放在finally里面 102 } catch (IOException e) { 103 // e.printStackTrace(); 104 System.out.println("用户注册释放资源失败"); 105 } 106 } 107 } 108 } 109 }
1 package cn.itcast.game; 2 3 import java.util.Scanner; 4 5 /** 6 * 这是猜数字小游戏 7 * 8 * @author 风清扬 9 * @version V1.1 10 * 11 */ 12 public class GuessNumber { 13 private GuessNumber() { 14 } 15 16 public static void start() { 17 // 产生一个随机数 18 int number = (int) (Math.random() * 100) + 1; 19 20 // 定义一个统计变量 21 int count = 0; 22 23 while (true) { 24 // 键盘录入一个数据 25 Scanner sc = new Scanner(System.in); 26 System.out.println("请输入数据[1-100]:"); 27 int guessNumber = sc.nextInt(); 28 29 count++; 30 31 // 判断 32 if (guessNumber > number) { 33 System.out.println("你猜的数据" + guessNumber + "大了"); 34 } else if (guessNumber < number) { 35 System.out.println("你猜的数据" + guessNumber + "小了"); 36 } else { 37 System.out.println("恭喜你," + count + "次就猜中了"); 38 break; 39 } 40 } 41 } 42 }
1 package cn.itcast.test; 2 3 import java.util.Scanner; 4 5 import cn.itcast.dao.UserDao; 6 import cn.itcast.dao.impl.UserDaoImpl; 7 import cn.itcast.game.GuessNumber; 8 import cn.itcast.pojo.User; 9 10 /** 11 * 这是用户测试类 12 * 13 * @author 风清扬 14 * @version V1.1 15 * 16 */ 17 public class UserTest { 18 public static void main(String[] args) { 19 // 为了能够回来 20 while (true) { 21 // 欢迎界面,给出选择项 22 System.out.println("--------------欢迎光临--------------"); 23 System.out.println("1 登录"); 24 System.out.println("2 注册"); 25 System.out.println("3 退出"); 26 System.out.println("请输入你的选择:"); 27 28 // 键盘录入选择,根据选择做不同的操作 29 Scanner sc = new Scanner(System.in); 30 // 为了后面的录入信息的方便,我所有的数据录入全部用字符串进行接收 31 String choiceString = sc.nextLine(); 32 33 // switch语句的多个地方要使用它,我就定义到外面 34 UserDao ud = new UserDaoImpl(); 35 36 // 经过简单的思考,我选择了switch,必须是JDK7以后,因为switch的表达式是字符串(JDK7的新特性) 37 switch (choiceString) { 38 case "1": 39 // 登录界面,请输入用户名和密码 40 System.out.println("--------------登录界面--------------"); 41 System.out.println("请输入用户名:"); 42 String username = sc.nextLine(); 43 System.out.println("请输入密码:"); 44 String password = sc.nextLine(); 45 46 // 调用登录功能 47 // UserDao ud = new UserDaomImpl(); 48 49 boolean flag = ud.isLogin(username, password); 50 if (flag) { 51 System.out.println("登录成功,可以开始玩游戏了"); 52 53 System.out.println("你玩吗?y/n"); 54 while (true) { 55 String resultString = sc.nextLine(); 56 if (resultString.equalsIgnoreCase("y")) { 57 // 玩游戏 58 GuessNumber.start(); 59 System.out.println("你还玩吗?y/n"); 60 } else { 61 break; 62 } 63 } 64 65 System.out.println("谢谢使用,欢迎下次再来"); 66 67 System.exit(0); 68 // break; // 这里的break,结束的是switch,而while循环没有结束 69 } else { 70 System.out.println("用户名或者密码有误,登录失败"); 71 } 72 break; 73 case "2": 74 // 注册界面,请输入用户名和密码 75 System.out.println("--------------注册界面--------------"); 76 System.out.println("请输入用户名:"); 77 String newUsername = sc.nextLine(); 78 System.out.println("请输入密码:"); 79 String newPassword = sc.nextLine(); 80 81 // 调用注册功能 82 // 多态用法 83 // UserDao ud = new UserDaoImpl(); 84 // 具体类用法 85 // UserDaoImpl udi = new UserDaoImpl(); 86 87 // 把用户名和密码封装到一个对象中 88 User user = new User(); 89 user.setUsername(newUsername); 90 user.setPassword(newPassword); 91 92 ud.regist(user); // 肯定注册成功,因为该方法的底层调用的是ArrayList的add()方法,该方法总是返回true。 93 System.out.println("注册成功"); 94 break; 95 case "3": 96 default: 97 System.out.println("谢谢使用,欢迎下次再来"); 98 System.exit(0); // 强制退出 99 break; 100 } 101 } 102 } 103 }
----------------------------------------------------------------------------- 2:数据操作流(操作基本数据类型的流)(理解) (1)操作基本数据类型的数据 (2)数据操作流对象的名称 DataInputStream 数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。 public DataInputStream(InputStream in) DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt")); DataOutputStream 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。 public DataOutputStream(OutputStream out) DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));
1 package cn.itcast_01; 2 3 import java.io.DataInputStream; 4 import java.io.DataOutputStream; 5 import java.io.FileInputStream; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 9 /* 10 * 可以读写基本数据类型的数据的流 11 * 12 * 数据输入流:DataInputStream(读) 13 * public DataInputStream(InputStream in) 14 * 数据输出流:DataOutputStream(写) 15 * public DataOutputStream(OutputStream out) 16 */ 17 public class DataStreamDemo { 18 public static void main(String[] args) throws IOException { 19 // 写 20 // write(); 21 22 // 读 23 read(); 24 } 25 26 private static void read() throws IOException { 27 // public DataInputStream(InputStream in) 28 // 创建数据输入流对象 29 DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt")); 30 31 // 读数据 32 byte b = dis.readByte(); 33 short s = dis.readShort(); 34 int i = dis.readInt(); 35 long l = dis.readLong(); 36 float f = dis.readFloat(); 37 double d = dis.readDouble(); 38 char c = dis.readChar(); 39 boolean bb = dis.readBoolean(); 40 41 // 释放资源 42 dis.close(); 43 44 System.out.println(b); 45 System.out.println(s); 46 System.out.println(i); 47 System.out.println(l); 48 System.out.println(f); 49 System.out.println(d); 50 System.out.println(c); 51 System.out.println(bb); 52 } 53 54 private static void write() throws IOException { 55 // public DataOutputStream(OutputStream out) 56 // 创建数据输出流对象 57 DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt")); 58 59 // 写数据 60 dos.writeByte(10); 61 dos.writeShort(100); 62 dos.writeInt(1000); 63 dos.writeLong(10000000000L); 64 dos.writeFloat(12.34F); 65 dos.writeDouble(12.56); 66 dos.writeChar('a'); 67 dos.writeBoolean(true); 68 69 // 释放资源 70 dos.close(); 71 } 72 }
----------------------------------------------------------------------------- 3:内存操作流(理解) (1)有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。 内存操作流一般用于处理临时存储信息,因为临时信息不需要保存,使用后就可以删除。 (2)三种内存操作流 A:操作字节数组 ByteArrayInputStream ByteArrayOutputStream B:操作字符数组(有中文时) CharArrayReader CharArrayWriter C:操作字符串 StringReader StringWriter
1 package cn.itcast_02; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.IOException; 6 7 /* 8 * 内存操作流:用于处理临时存储信息的,程序结束,数据就从内存中消失。 9 * 10 * 三种内存操作流 11 * 操作字节数组:(没有中文时) 12 * ByteArrayInputStream 13 * ByteArrayOutputStream 14 * 操作字符数组:(有中文时) 15 * CharArrayReader 16 * CharArrayWriter 17 * 操作字符串: 18 * StringReader 19 * StringWriter 20 */ 21 public class ByteArrayStreamDemo { 22 public static void main(String[] args) throws IOException { 23 // 写数据 24 // public ByteArrayOutputStream() 25 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 26 27 for (int x = 0; x < 10; x++) { 28 baos.write(("hello" + x).getBytes()); // String类的方法:把字符串转成字节数组 29 } 30 31 // 释放资源,通过查看源码我们知道这里什么都没做(空实现),所以根本不需要close() 32 // baos.close(); 33 34 // 把数据转为字节数组 35 // public byte[] toByteArray() 36 byte[] bys = baos.toByteArray(); 37 38 // 读数据 39 // public ByteArrayInputStream(byte[] bys) 40 ByteArrayInputStream bais = new ByteArrayInputStream(bys); 41 42 int by = 0; 43 while ((by = bais.read()) != -1) { 44 System.out.print((char) by); 45 } 46 47 // 释放资源 48 // bais.close(); 49 } 50 }
----------------------------------------------------------------------------- 4:打印流(掌握) (1)字节打印流 PrintStream 字符打印流 PrintWriter (2)打印流的特点 A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。 B:可以操作任意类型的数据。 C:如果启动了自动刷新,则在调用println()、printf() 或 format() 方法的时候,能够自动换行并刷新。 D:该流是可以直接操作文本文件的。 问题:哪些流可以直接操作文件呢? FileInputStream FileOutputStream FileReader FileWriter PrintStream PrintWriter 看API,如果其构造方法能够同时接收File类型和String类型的参数,一般都是可以直接操作文件的。 流分类: 基本流:就是能够直接读写文件的。 高级流:在基本流基础上提供了一些其他的功能。 -------------------------------------- (3)复制文本文件 // 封装数据源 BufferedReader br = new BufferedReader(new FileReader("a.txt")); // 封装目的地 PrintWriter pw = new PrintWriter(new FileWriter("b.txt"), true); // 需要启动自动刷新 String line = null; while ((line = br.readLine()) != null) { pw.println(line); } pw.close(); br.close();
1 package cn.itcast_03; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 import java.io.PrintWriter; 9 10 /* 11 * 需求:把 DataStreamDemo.java文件的内容 复制到 Copy.java 中 12 * 数据源: 13 * DataStreamDemo.java --> 读取数据 --> FileReader --> BufferedReader 14 * 目的地: 15 * Copy.java --> 写出数据 --> FileWriter --> BufferedWriter --> PrintWriter 16 */ 17 public class CopyFileDemo { 18 public static void main(String[] args) throws IOException { 19 // 以前的版本 20 // 封装数据源 21 // BufferedReader br = new BufferedReader(new FileReader("DataStreamDemo.java")); 22 // 封装目的地 23 // BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java")); 24 25 // String line = null; 26 // while ((line = br.readLine()) != null) { 27 // bw.write(line); 28 // bw.newLine(); 29 // bw.flush(); 30 // } 31 32 // bw.close(); 33 // br.close(); 34 35 // 打印流的改进版 36 // 封装数据源 37 BufferedReader br = new BufferedReader(new FileReader("DataStreamDemo.java")); 38 // 封装目的地 39 PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true); // 需要启动自动刷新 40 41 String line = null; 42 while ((line = br.readLine()) != null) { 43 pw.println(line); 44 } 45 46 pw.close(); 47 br.close(); 48 } 49 }
----------------------------------------------------------------------------- 5:标准输入输出流(理解) (1)System类下面有这样的两个字段(字段=成员变量:用静态修饰,可以通过类名直接调用) public static final InputStream in 标准输入流,默认是从键盘获取数据的。 public static final PrintStream out 标准输出流,默认的输出设备是显示器。 InputStream is = System.in; PrintStream ps = System.out; OutputStream os = ps; // 多态 public static final PrintStream errerr 标准错误输出流 -------------------------------------- (2)三种键盘录入方式 A:main方法的args接收参数 B:把System.in用字符缓冲输入流BufferedReader进行包装后再使用(其实这样不方便,我们一般直接使用Scanner类的构造方法来接收System.in来进行输入了,但是呢?这种方法以后也不用,就业班我们用浏览器界面的方式) BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); C:Scanner(JDK5以后的) Scanner sc = new Scanner(System.in); String s = sc.nextLine(); int x = sc.nextInt() -------------------------------------- (3)输出语句的原理和如何使用标准输出流输出数据 A:输出语句的原理原理:输出语句的本质是IO流 System.out.println("helloworld"); PrintStream ps = System.out; ps.println("helloworld"); B:把System.out用字符缓冲输出流BufferedWriter进行包装后再使用(其实这样也不方便,我们一般直接使用System.out来进行输出了) BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
1 package cn.itcast_04; 2 3 import java.io.PrintStream; 4 5 /* 6 * 标准输入输出流 7 * System类中的两个成员变量: 8 * public static final InputStream in “标准”输入流。 9 * public static final PrintStream out “标准”输出流。 10 * 11 * InputStream is = System.in; 12 * PrintStream ps = System.out; 13 */ 14 public class SystemOutDemo { 15 public static void main(String[] args) { 16 // 由这里的讲解我们就知道了,这个输出语句其本质是IO流操作,把数据输出到控制台。 17 System.out.println("helloworld"); 18 19 // 获取标准输出流对象 20 PrintStream ps = System.out; 21 ps.println("helloworld"); 22 23 ps.println(); 24 25 // ps.print(); // PrintStream类没有这个方法 26 27 // System.out.println(); 28 // System.out.print(); 29 } 30 }
1 package cn.itcast_04; 2 3 import java.io.BufferedWriter; 4 import java.io.IOException; 5 import java.io.OutputStreamWriter; 6 /* 7 * 转换流的应用。 8 */ 9 public class SystemOutDemo2 { 10 public static void main(String[] args) throws IOException { 11 // 获取标准输入流 12 // PrintStream ps = System.out; 13 // OutputStream os = ps; 14 // OutputStream os = System.out; // 多态 15 // 我能不能按照刚才使用标准输入流的方式把数据输出到控制台呢? 16 // OutputStreamWriter osw = new OutputStreamWriter(os); 17 // BufferedWriter bw = new BufferedWriter(osw); 18 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); 19 20 bw.write("hello"); 21 bw.newLine(); 22 // bw.flush(); 23 bw.write("world"); 24 bw.newLine(); 25 // bw.flush(); 26 bw.write("java"); 27 bw.newLine(); 28 bw.flush(); 29 30 bw.close(); 31 } 32 }
1 package cn.itcast_04; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 /* 8 * System.in 标准输入流。默认是从键盘获取数据的。 9 * 10 * 键盘录入数据: 11 * A:main方法的args接收参数。 12 * java HelloWorld hello world java 13 * B:Scanner(JDK5以后的) 14 * Scanner sc = new Scanner(System.in); 15 * String s = sc.nextLine(); 16 * int x = sc.nextInt() 17 * C:通过字符缓冲流包装标准输入流实现 18 * BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 19 */ 20 public class SystemInDemo { 21 public static void main(String[] args) throws IOException { 22 // 获取标准输入流 23 // InputStream is = System.in; 24 // 字节流只能一次读取一个字节或者一个字节数组的一部分,那么我要一次获取一行数据,行不行呢? 答:行。 25 // 怎么实现呢? 答:要想实现,首先你得知道一次读取一行数据的方法是哪个呢?答:readLine()方法。 26 // 而这个方法在哪个类中呢? 答:在BufferedReader类中。 27 // 所以,你这次应该创建BufferedReader的对象,但是底层还是使用的是标准输入流。 28 // BufferedReader br = new BufferedReader(is); 29 // 按照我们的推想,现在应该可以了,但是却报错了。 30 // 原因是:字符缓冲流只能针对字符流操作,而你现在是字节流,所以不能使用? 31 // 那么,我偏要使用,请大家给我一个解决方案? 答:把字节流转换为字符流,然后在通过字符缓冲流操作 32 // InputStreamReader isr = new InputStreamReader(is); 33 // BufferedReader br= new BufferedReader(isr); 34 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 35 36 System.out.println("请输入一个字符串:"); 37 String line = br.readLine(); 38 System.out.println("你输入的字符串是:" + line); 39 40 System.out.println("请输入一个整数:"); 41 // int i = Integer.parseInt(br.readLine()); // Integer类的解析方法,把字符串解析为int类型。 42 line = br.readLine(); 43 int i = Integer.parseInt(line); 44 System.out.println("你输入的整数是:" + i); 45 } 46 }
----------------------------------------------------------------------------- 6:随机访问流(理解) (1)RandomAccessFile类不属于流,是Object类的子类。 但它融合了InputStream和OutputStream的功能。 此类的实例支持对文件的随机访问读取和写入。 RandomAccessFile类的构造方法: public RandomAccessFile(String name, String mode) 第一个参数是文件路径,第二个参数是操作文件的模式。 模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据。 // 创建随机访问流对象 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); // 可读可写,写文件的时候,文件不存在,就创建。 可以按照文件指针的位置写数据和读数据。 该文件指针可以通过 getFilePointer()方法读取(从0开始计数,以字节为单位),并通过seek(int i)方法设置。 (2)案例: A:写数据 B:读数据 C:获取和改变文件指针的位置 示例代码如下:
1 package cn.itcast_05; 2 3 import java.io.IOException; 4 import java.io.RandomAccessFile; 5 6 /* 7 * 随机访问流: 8 * RandomAccessFile类不属于流,是Object类的子类。 9 * 但它融合了InputStream和OutputStream的功能。 10 * 此类的实例支持对文件的随机访问读取和写入。 11 * 12 * RandomAccessFile类的构造方法: 13 * public RandomAccessFile(String name, String mode) 14 * 第一个参数是文件路径,第二个参数是操作文件的模式。 15 * 模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据 。 16 */ 17 public class RandomAccessFileDemo { 18 public static void main(String[] args) throws IOException { 19 write(); 20 read(); 21 } 22 23 private static void read() throws IOException { 24 // 创建随机访问流对象 25 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); // 可读可写,写文件的时候,文件不存在,就创建。 26 27 // 该文件指针可以通过 getFilePointer()方法读取(从0开始计数,以字节为单位),并通过seek(int i)方法设置。 28 System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); // 0 29 int i = raf.readInt(); 30 System.out.println(i); 31 32 System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); // 4 33 char ch = raf.readChar(); 34 System.out.println(ch); 35 36 System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); // 6 = 4 + 2 37 String s = raf.readUTF(); // 从当前文件指针开始读取前两个字节,随后的字节然后解释为 UTF-8 修改版格式的字节编码字符,并转换为字符。UTF-8:1个中文字符=3个字节 38 System.out.println(s); 39 40 System.out.println("当前文件的指针位置是:" + raf.getFilePointer()); // 14 = 6 + 2 + 3 + 3 41 42 43 raf.seek(0); 44 i = raf.readInt(); 45 System.out.println(i); // 100 46 47 // 我不想重头开始了,我就要读取a,怎么办呢? 48 raf.seek(4); 49 ch = raf.readChar(); 50 System.out.println(ch); // a 51 52 raf.seek(6); 53 s = raf.readUTF(); 54 System.out.println(s); // 中国 55 } 56 57 private static void write() throws IOException { 58 // 创建随机访问流对象 59 RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw"); // 可读可写,写文件的时候,文件不存在,就创建。 60 61 // 怎么玩呢? 62 raf.writeInt(100); 63 raf.writeChar('a'); 64 raf.writeUTF("中国"); 65 66 raf.close(); 67 } 68 }
----------------------------------------------------------------------------- 7:合并流(理解) (1)SequenceInputStream类的概述 可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。 (2)SequenceInputStream类构造方法 A:public SequenceInputStream(InputStream s1, InputStream s2) 2个输入流合并 B:public SequenceInputStream(Enumeration<? extends InputStream> e) 多个输入流合并 示例代码如下:
1 package cn.itcast_06; 2 3 import java.io.BufferedOutputStream; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.SequenceInputStream; 9 10 /* 11 * 以前的操作: 12 * a.txt --> b.txt 13 * c.txt --> d.txt 14 * 15 * 现在想要: 16 * a.txt+b.txt --> c.txt 17 */ 18 public class SequenceInputStreamDemo { 19 public static void main(String[] args) throws IOException { 20 // public SequenceInputStream(InputStream s1, InputStream s2) 21 // 需求:把ByteArrayStreamDemo.java和DataStreamDemo.java的内容复制到Copy.java中 22 InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); 23 InputStream s2 = new FileInputStream("DataStreamDemo.java"); 24 SequenceInputStream sis = new SequenceInputStream(s1, s2); 25 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java")); 26 27 // 如何读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写 28 byte[] bys = new byte[1024]; 29 int len = 0; 30 while ((len = sis.read(bys)) != -1) { 31 bos.write(bys, 0, len); 32 } 33 34 bos.close(); 35 sis.close(); 36 s2.close(); 37 s1.close(); 38 } 39 }
1 package cn.itcast_06; 2 3 import java.io.BufferedOutputStream; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.io.SequenceInputStream; 9 import java.util.Enumeration; 10 import java.util.Vector; 11 12 /* 13 * 以前的操作: 14 * a.txt --> b.txt 15 * c.txt --> d.txt 16 * e.txt --> f.txt 17 * 18 * 现在想要: 19 * a.txt+b.txt+c.txt --> d.txt 20 */ 21 public class SequenceInputStreamDemo2 { 22 public static void main(String[] args) throws IOException { 23 // 需求:把下面的三个文件的内容复制到Copy.java中 24 // ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java 25 26 // public SequenceInputStream(Enumeration<? extends InputStream> e) 27 // public SequenceInputStream(Enumeration e) 28 // 通过简单的回顾我们知道了:Enumeration是Vector类中的一个方法的返回值类型。 29 // Vector类的方法:public Enumeration<E> elements() 30 31 // 创建集合对象 32 Vector<InputStream> v = new Vector<InputStream>(); 33 34 // 创建流对象 35 InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java"); 36 InputStream s2 = new FileInputStream("CopyFileDemo.java"); 37 InputStream s3 = new FileInputStream("DataStreamDemo.java"); 38 39 // 把流对象添加进集合 40 v.add(s1); 41 v.add(s2); 42 v.add(s3); 43 44 // 通过集合对象调用方法 45 Enumeration<InputStream> en = v.elements(); 46 47 48 SequenceInputStream sis = new SequenceInputStream(en); 49 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java")); 50 51 // 如何读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写 52 byte[] bys = new byte[1024]; 53 int len = 0; 54 while ((len = sis.read(bys)) != -1) { 55 bos.write(bys, 0, len); 56 } 57 58 bos.close(); 59 sis.close(); 60 } 61 }
----------------------------------------------------------------------------- 8:序列化流(对象操作流)(理解) (1)可以把对象写入文本文件或者在网络中传输。 (2)如何实现序列化呢? 让被序列化的对象所属的类实现序列化接口。 该接口是一个标记接口。没有方法需要实现。 (3)注意问题: 1.把数据写到文件后,再去修改类的成员变量会产生一个问题。如何解决该问题呢? 在被序列化的对象所属的类文件中,给出一个固定的序列化id值。(序列化值:序列化值与实现序列化接口的类的成员变量有关) 而且,这样也可以解决黄色警告线问题。 2.一个已经实现序列化的类中可能有很多的成员变量,有些成员变量我不想进行序列化。请问该怎么办呢? 答:使用transient关键字声明不需要序列化的成员变量。 (4)面试题 什么是序列化? 对象 -->写入 文件 如何实现序列化? 什么是反序列化? 文件 -->还原 对象 对象序列化:是将对象状态转换为可保持或传输的过程。一般的格式是与平台无关的二进制流,可以将这种二进制流持久保存在磁盘上,也可以通过网络将这种二进制流传输到另一个网络结点。 对象反序列化:是指把这种二进制流数据还原成对象。 示例代码如下:
1 package cn.itcast_07; 2 3 import java.io.Serializable; 4 5 /* 6 * NotSerializableException:未序列化异常 7 * 8 * 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。 9 * 该接口里面居然没有任何方法,类似于这种没有方法的接口被称为标记接口。 10 * 11 * 12 * java.io.InvalidClassException: 13 * cn.itcast_07.Person; local class incompatible: 14 * stream classdesc serialVersionUID = -2071565876962058344, 15 * local class serialVersionUID = -8345153069362641443 16 * 17 * 把Person类的成员变量 private int age; 改为 int age;后,不重新写数据,而是只再重新读数据,会出现问题? 18 * 为什么会有问题呢? 19 * 因为Person类实现了序列化接口,那么它本身也应该有一个标记值。 20 * (标记值=序列化值:序列化值与实现序列化接口的类的成员变量有关) 21 * 这个标记值假设是100。 22 * 23 * 以前: 24 * Person.class --> id=100 25 * wirte数据: oos.txt --> id=100 26 * read数据: oos.txt --> id=100 27 * 28 * 现在: 29 * Person.class --> id=200 30 * wirte数据: oos.txt --> id=100 31 * read数据: oos.txt --> id=100 32 * 33 * 我们在实际开发中,可能还需要使用以前写过的数据,暂时不能重新写入。该怎么办呢? 34 * 回想一下原因是:因为它们的id值不匹配。 35 * 36 * 每次修改.java文件的内容的时候,.class文件的id值都会发生改变。 37 * 而读取文件的时候,会和.class文件中的id值进行匹配。所以,就会出问题。 38 * 39 * 但是呢,如果我有办法,让这个id值在.java文件中是一个固定的值,这样,你修改文件的时候,这个id值还会发生改变吗? 答:不会。 40 * 现在的关键是我如何能够知道这个id值如何表示的呢? 答:不用担心,你不用记住,也没关系,点击鼠标即可。 41 * 你难道没有看到黄色警告线吗? 42 * 43 * 我们要知道的是: 44 * 看到某个类实现了序列化接口的时候,要想解决黄色警告线的问题,就可以自动产生一个序列化id值。 45 * 而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。 46 * 47 * 注意: 48 * 一个已经实现序列化的类中可能有很多的成员变量,有些成员变量我不想进行序列化。请问该怎么办呢? 49 * 答:使用transient关键字声明不需要序列化的成员变量。 50 */ 51 public class Person implements Serializable { 52 private static final long serialVersionUID = -2071565876962058344L; 53 54 private String name; 55 56 // 使用transient关键字声明不需要序列化的成员变量 57 private transient int age; 58 59 public Person() { 60 super(); 61 } 62 63 public Person(String name, int age) { 64 super(); 65 this.name = name; 66 this.age = age; 67 } 68 69 public String getName() { 70 return name; 71 } 72 73 public void setName(String name) { 74 this.name = name; 75 } 76 77 public int getAge() { 78 return age; 79 } 80 81 public void setAge(int age) { 82 this.age = age; 83 } 84 85 @Override 86 public String toString() { 87 return "Person [name=" + name + ", age=" + age + "]"; 88 } 89 }
1 package cn.itcast_07; 2 3 import java.io.FileInputStream; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.ObjectInputStream; 7 import java.io.ObjectOutputStream; 8 9 /* 10 * ObjectOutputStream序列化流: 11 * 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。 12 * 通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。 13 * 14 * 把对象按照流一样的方式存入文本文件或者在网络中传输。 15 * 对象 --> 流数据(ObjectOutputStream) 16 * 17 * 18 * ObjectInputStream反序列化流: 19 * ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。 20 * 21 * 把文本文件中的流对象数据或者网络中的流对象数据还原成对象。 22 * 流数据 --> 对象(ObjectInputStream) 23 */ 24 public class ObjectStreamDemo { 25 public static void main(String[] args) throws IOException, ClassNotFoundException { 26 // 由于我们要对对象进行序列化,所以我们先自定义一个类 27 // 序列化数据其实就是把对象写到文本文件 28 // write(); 29 30 read(); 31 } 32 33 private static void read() throws IOException, ClassNotFoundException { 34 // 创建反序列化对象 35 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt")); 36 37 // 还原对象 38 Object obj = ois.readObject(); 39 40 // 释放资源 41 ois.close(); 42 43 // 输出对象:默认输出的是对象的toString()方法 44 System.out.println(obj); 45 } 46 47 private static void write() throws IOException { 48 // 创建序列化流对象 49 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt")); 50 51 // 创建对象 52 Person p = new Person("林青霞", 27); 53 54 // ObjectOutputStream类的方法:public final void writeObject(Object obj) 55 // 将指定的对象写 ObjectOutputStream 56 oos.writeObject(p); 57 58 // 释放资源 59 oos.close(); 60 } 61 }
----------------------------------------------------------------------------- 9:Properties属性集合类(理解) (1)Properties类的概述 是一个集合类,是Hashtable类的子类。说明是一个Map集合。 是一个可以和IO流相结合使用的集合类。 该Properties集合中的数据可以保存在流中或者从流中加载。属性列表中每个键及其对应值都是一个字符串。 该类不是一个泛型类,在使用的时候就不能加泛型。 (2)Properties类的特有功能 A:public Object setProperty(String key, String value) 添加元素 B:public String getProperty(String key) 获取元素 C:public Set<String> stringPropertyNames() 获取所有的键的集合 -------------------------------------- (3)Properties和IO流的结合使用 把键值对形式的文本文件内容加载到集合中 public void load(Reader reader) public void load(InputStream inStream) 把集合中的数据存储到文本文件中 public void store(Writer writer, String comments) public void store(OutputStream out, String comments)
comments:属性列表的描述 注意:这个文件的数据形式必须是键值对形式,这里的集合必须是Properties集合。 示例代码如下:
1 package cn.itcast_08; 2 3 import java.util.Properties; 4 import java.util.Set; 5 6 /* 7 * Properties类的特有功能: 8 * public Object setProperty(String key, String value) 添加元素 9 * public String getProperty(String key) 获取元素 10 * public Set<String> stringPropertyNames() 获取所有的键的集合 11 * 12 */ 13 public class PropertiesDemo2 { 14 public static void main(String[] args) { 15 // 创建集合对象 16 Properties prop = new Properties(); 17 18 // 添加元素 19 prop.setProperty("张三", "30"); 20 prop.setProperty("李四", "40"); 21 prop.setProperty("王五", "50"); 22 prop.setProperty("王五", "100"); 23 24 // Properties类的特有功能 25 // public Set<String> stringPropertyNames() 获取所有的键的集合 26 Set<String> set = prop.stringPropertyNames(); 27 for (String key : set) { 28 String value = prop.getProperty(key); 29 System.out.println(key + "---" + value); 30 } 31 } 32 } 33 34 /* 35 * 思想: 36 * java中,父类的方法传入的形参的数据类型是泛型,子类的方法的形参想只要一种确定的数据类型,子类该如何做呢? 37 * 答:那么子类可以重新写一个方法,形参传入的是一种想要的数据类型,而子类方法里面调用的还是父类的方法。 38 * 39 * 示例代码如下: 40 * 41 * class Hashtalbe<K, V> { 42 * public V put(K key, V value) { 43 * ... 44 * } 45 *} 46 * 47 * class Properties extends Hashtable { 48 * public V setProperty(String key, String value) { 49 * return put(key, value); 50 * } 51 * } 52 */
1 package cn.itcast_08; 2 3 import java.util.Properties; 4 import java.util.Set; 5 6 /* 7 * Properties:是属性集合类。是一个可以和IO流相结合使用的集合类。 8 * 9 * Properties 10 * 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 11 * 12 * 是Hashtable的子类,说明是一个Map集合。 13 */ 14 public class PropertiesDemo { 15 public static void main(String[] args) { 16 // Properties作为Map集合的使用 17 // 下面这种用法是错误的,一定要看API,如果没有<>,就说明该类不是一个泛型类,在使用的时候就不能加泛型。 18 // Properties<String, String> prop = new Properties<String, String>(); 19 20 // 创建集合类 21 Properties prop = new Properties(); 22 23 // 添加元素 24 prop.put("it002", "hello"); 25 prop.put("it001", "world"); 26 prop.put("it003", "java"); 27 28 // System.out.println("prop:" + prop); 29 30 // 作为Map集合的使用 31 // 遍历集合 32 Set<Object> set = prop.keySet(); 33 for (Object key : set) { 34 Object value = prop.get(key); 35 System.out.println(key + "---" + value); 36 } 37 } 38 }
1 package cn.itcast_08; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 import java.io.Reader; 7 import java.io.Writer; 8 import java.util.Properties; 9 10 /* 11 * 这里的集合必须是Properties集合: 12 * public void load(Reader reader) 把文件中的数据加载到集合中 13 * public void store(Writer writer, String comments) 把集合中的数据存储到文件 14 * 15 * 应用: 16 * 单机版游戏:进度保存和加载。 17 * 三国群英传,三国志,仙剑奇侠传... 18 * 19 * 吕布=1 20 * 方天画戟=1 21 */ 22 public class PropertiesDemo3 { 23 public static void main(String[] args) throws IOException { 24 // myLoad(); 25 26 myStore(); 27 } 28 29 // 把集合中的数据存储到文件 30 private static void myStore() throws IOException { 31 // 创建集合对象 32 Properties prop = new Properties(); 33 34 prop.setProperty("林青霞", "27"); 35 prop.setProperty("武鑫", "30"); 36 prop.setProperty("刘晓曲", "18"); 37 38 // public void store(Writer writer, String comments) 把集合中的数据存储到文件 comments:属性列表的描述 39 Writer w = new FileWriter("name.txt"); 40 prop.store(w, "helloworld"); 41 w.close(); 42 } 43 44 // 把文件中的数据加载到集合中 45 private static void myLoad() throws IOException { 46 Properties prop = new Properties(); 47 48 // public void load(Reader reader) 把文件中的数据读取到集合中 注意:这个文件的数据形式必须是键值对形式。 49 Reader r = new FileReader("prop.txt"); 50 prop.load(r); 51 r.close(); 52 53 System.out.println("prop:" + prop); 54 } 55 }
-------------------------------------- (4)案例 A:根据给定的文本文件判断是否有键为"lisi"的,如果有就修改其值为100(键相同,值覆盖) 1:把文件中的数据加载到集合中 2:遍历集合,获取得到每一个键 3:判断键是否有为"lisi"的,如果有就修改其值为"100" 4:把集合中的数据重新存储到文件中
1 package cn.itcast_08; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 import java.io.Reader; 7 import java.io.Writer; 8 import java.util.Properties; 9 import java.util.Set; 10 11 /* 12 * 我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。 13 * 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100” 14 * 15 * 分析: 16 * A:把文件中的数据加载到集合中 17 * B:遍历集合,获取得到每一个键 18 * C:判断键是否有为"lisi"的,如果有就修改其值为"100" 19 * D:把集合中的数据重新存储到文件中 20 */ 21 public class PropertiesTest { 22 public static void main(String[] args) throws IOException { 23 // 把文件中的数据加载到集合中 24 Properties prop = new Properties(); 25 Reader r = new FileReader("user.txt"); 26 prop.load(r); 27 r.close(); 28 29 // 遍历集合,获取得到每一个键 30 Set<String> set = prop.stringPropertyNames(); 31 for (String key : set) { 32 // 判断键是否有为"lisi"的,如果有就修改其值为"100" 33 if ("lisi".equals(key)) { 34 prop.setProperty(key, "100"); 35 break; 36 } 37 } 38 39 // 把集合中的数据重新存储到文件中 40 Writer w = new FileWriter("user.txt"); 41 prop.store(w, null); 42 w.close(); 43 } 44 }
B:写一个程序实现控制猜数字小游戏程序不能玩超过5次(即该程序不能启动超过5次)
1 count=0
1 package cn.itcast_08; 2 3 import java.util.Scanner; 4 5 /** 6 * 这是猜数字小游戏 7 * 8 * @author 风清扬 9 * @version V1.1 10 * 11 */ 12 public class GuessNumber { 13 private GuessNumber() { 14 } 15 16 public static void start() { 17 // 产生一个随机数 18 int number = (int) (Math.random() * 100) + 1; 19 20 // 定义一个统计变量 21 int count = 0; 22 23 while (true) { 24 // 键盘录入一个数据 25 Scanner sc = new Scanner(System.in); 26 System.out.println("请输入数据[1-100]:"); 27 int guessNumber = sc.nextInt(); 28 29 count++; 30 31 // 判断 32 if (guessNumber > number) { 33 System.out.println("你猜的数据" + guessNumber + "大了"); 34 } else if (guessNumber < number) { 35 System.out.println("你猜的数据" + guessNumber + "小了"); 36 } else { 37 System.out.println("恭喜你," + count + "次就猜中了"); 38 break; 39 } 40 } 41 } 42 }
1 package cn.itcast_08; 2 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 import java.io.Reader; 7 import java.io.Writer; 8 import java.util.Properties; 9 10 /* 11 * 我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。 12 */ 13 public class PropertiesTest2 { 14 public static void main(String[] args) throws IOException { 15 // 思路:读取某个地方(文件)的数据,如果次数不大于5,可以继续玩。否则就提示"游戏试玩已结束,请付费。" 16 17 // 把数据加载到集合中 18 Properties prop = new Properties(); 19 Reader r = new FileReader("count.txt"); 20 prop.load(r); 21 r.close(); 22 23 // 我自己的程序,我当然知道里面的键是谁,键是count 24 String value = prop.getProperty("count"); 25 int number = Integer.parseInt(value); 26 27 if (number > 5) { 28 System.out.println("游戏试玩已结束,请付费。"); 29 System.exit(0); 30 } else { 31 number++; 32 prop.setProperty("count", String.valueOf(number)); // 键相同,值覆盖 33 34 // 把集合中的数据重新存储到文件中 35 Writer w = new FileWriter("count.txt"); 36 prop.store(w, null); 37 w.close(); 38 39 GuessNumber.start(); 40 } 41 } 42 }
----------------------------------------------------------------------------- 10:NIO(新IO)(了解) (1)JDK4出现的NIO,对以前的IO操作进行了优化,提高了效率。但是大部分我们看到的还是以前的IO(以前的是基础)。 新IO使用了不同的方式来处理输入输出,采用内存映射文件的方式,将文件或者文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件了,这种方式效率比旧IO要高很多。 (2)JDK7的NIO的使用 Path接口:与平台无关的路径 Paths类:包含了返回Path的静态方法(2个:只讲了一个) public static Path get(URI uri) 根据给定的URI来确定文件路径 Files类:操作文件的工具类。提供了大量的方法。 public static long copy(Path source, OutputStream out) 复制文件 public static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options) 把集合的数据写到文件 (3)案例 复制文本文件 把集合中的数据写到文本文件 示例代码如下:
1 package cn.itcast_09; 2 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.nio.charset.Charset; 6 import java.nio.file.Files; 7 import java.nio.file.Paths; 8 import java.util.ArrayList; 9 10 /* 11 * nio包在JDK4出现,提高了IO流的操作效率。但是目前还不是大范围的使用。 12 * 有空的话了解下,有问题再问我。 13 * 14 * JDK7的之后的nio: 15 * Path接口:与平台无关的路径 16 * Paths:包含了返回Path的静态方法(2个) 17 * public static Path get(URI uri) 根据给定的URI来确定文件路径 18 * Files:提供了静态方法供我们使用 19 * public static long copy(Path source, OutputStream out) 复制文件 20 * public static Path write(Path path, Iterable<? extends CharSequence> lines, Charset cs, OpenOption... options) 把集合的数据写到文件 21 */ 22 public class NIODemo { 23 public static void main(String[] args) throws IOException { 24 // 复制文件 25 // public static long copy(Path source, OutputStream out) 复制文件 26 Files.copy(Paths.get("HelloWorld.java"), new FileOutputStream("Copy.java")); 27 28 // 把集合中的数据写到文本文件 29 ArrayList<String> array = new ArrayList<String>(); 30 array.add("hello"); 31 array.add("world"); 32 array.add("java"); 33 array.add("陈明军"); 34 Files.write(Paths.get("array.txt"), array, Charset.forName("UTF-8")); 35 } 36 37 }
=============================================================================