黑马程序员--Java之IO流
2015-08-14 16:10
561 查看
——- android培训、java培训、期待与您交流! ———-
我们要想实现IO的操作,就必须知道硬盘上文件的表现形式
文件和目录路径名的抽象表示形式
方案1:
方案2:过滤器
批量修改同一格式文件的文件名:(这些文件名需要有规律)
获取指定目录下所有格式或指定格式的文件:
删除文件夹(带内容):
清空指定文件夹内容:
流向:(以java程序为参照物)
输入流:读取数据
输出流:写入数据
数据类型:
字节流
字节输入流:
读取数据:InputStream
字节输出流:
写入数据:OutputStream
字符流
字符输入流:
读取数据:Reader
字符输出流:
写入数据:Writer
用系统自带的笔记本打开,读得懂的可以用字符流,读不懂就只能用字节流。
创建字节流对象一共做了三件事:
如果a.txt文件不存在,就创建一个a.txt文件
创建fos对象
把fos对象指向a.txt文件
write()方法:
public void write(byte[] b)throws IOException
public void write(byte[] b,int off,int len)throwsIOException
public abstract void write(int b)throws IOException
如果write()方法需要传入的是字节数组,把需要传入的字符串转为字节数组传入就行。
close():释放资源
让流对象变成垃圾,可以被垃圾回收器回收
通知系统释放跟该文件相关的资源
数据换行和追加写入
数据换行:
不同的系统识别不同的换行符号
windows:\r\n
linux:\n
MAC:\R
常见的高级记事本所有的都可以识别。
数据追加写入:
利用构造方法可以实现数据追加写入,没运行一次就写入一次。
汉字的存储
常见编码表:
ACSII表:7位表示一个数据,最高位为符号位。
ISO-8859-1:拉丁码表,8位表示一个数据。
BIG5:通行于台湾,香港地区的繁体字编码表。俗称“大五码”
UTF-8:最多用三个字节来表示一个字符。能用一个就用一个,现在不行就用三个。
默认的编码表跟随系统,系统为简体中文,默认的编码表就为简体中文。
flush()和close()的区别:
flush():刷新缓冲区,刷新之后流对象还可以继续使用。
close():关闭流对象之前会刷新一次缓冲区,关闭之后流对象就不能继续使用。
合并流读写多个文件
对象类:
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常
使用transient关键字修饰的成员变量就不能进行序列化
Properties特殊功能
Properties的load()和store()方法
File
用一张图简单介绍一下IO流。我们要想实现IO的操作,就必须知道硬盘上文件的表现形式
文件和目录路径名的抽象表示形式
构造方法
package com.kxg.file; import java.io.File; /* * File类: * 文件和目录路径名的抽象表示形式。 * 构造方法: * public File(String pathname):根据路径得到File对象 * public File(String parent,String child):根据一个目录和一个子文件/目录得到File对象 * public File(File parent,String child):根据一个父File对象和一个子文件/目录得到File对象 * * 三种构造方法结果都是一样的,用第一个构造方法即可。 */ public class FileDemo { public static void main(String[] args) { // public File(String pathname) // 把xiaoguang.java封装成为一个File对象。 File f =new File ("D:\\Demo\\xiaoguang.java"); // public File(String parent,String child) File f2 = new File("D:\\Demo","xiaoguang.java2"); // public File(File parent,String child) File f3 = new File("D:\\Demo"); File f4 = new File(f3,"xiaoguang.java3"); } }
创建功能
package com.kxg.file; import java.io.File; import java.io.IOException; /* * File类创建功能: * public boolean createNewFile():创建文件,如果存在不创建 * public boolean mkdir():创建文件夹,如果存在就不创建 * public boolean mkdirs():创建文件夹,如果上级文件夹不存在,直接创建 * * File类的删除功能: * public boolean delete() * 注意:如果创建文件或者文件夹的时候,忘记写盘符路径,默认在项目路径下。 * java中删除不走回收站 * 不能删除非空文件夹 */ public class FileDemo2 { public static void main(String[] args) throws IOException { // 创建文件夹 File f = new File("D:\\Test"); System.out.println(f.mkdir()); // 在已存在文件夹内创建文件 File f2 = new File("D:\\Test\\xiaoguang.java"); System.out.println(f2.createNewFile()); // 同时创建不存在的文件夹和文件 // 出错提示:系统找不到指定的路径,不能同时创建文件夹和文件,必须先创建目录才能在此目录中创建文件 // File f3 = new File("D:\\Test2\\xiaoguang.java"); // System.out.println(f3.createNewFile()); // 同时创建不存在的文件夹 // 返回false,说明创建失败,同样也是因为上级文件夹不存在。 File f4 = new File("D:\\Test2\\Test3"); System.out.println(f4.mkdir()); // public boolean mkdirs() File f5 = new File("D:\\Test2\\xiaoguang.java"); System.out.println(f5.mkdirs()); // 需要注意:mkdirs只能创建文件夹,xiaoguang.java不是文件,而是一个以这个命名的文件夹 // 创建文件夹和文件需要分为两个步骤才能完成。 File f6 = new File("D:\\Test2\\xiaoguang.java\\xiaoguang.java"); System.out.println(f6.createNewFile()); // public boolean delete() f6.delete(); } }
重命名功能
package com.kxg.file; import java.io.File; import java.io.IOException; /* * File类的重命名功能: * public boolean renameTo(File dest) * * 绝对路径:有盘符,路径名完整的路径。 * 相对路径:没有盘符,相对于java程序的路径,在项目中。 * * 做重命名操作时,路径相同,就重命名。 * 如果不相同重命名执行了两个操作: * 1.重命名 * 2.剪切到绝对路径下 */ public class FileDemo3 { public static void main(String[] args) throws IOException { // 封装文件 File f = new File("xiao.txt"); // 封装新文件名 File f2 = new File("guang.avi"); f.renameTo(f2); File f3 = new File("D:\\Test\\xiao.exe"); f2.renameTo(f3); } }
判断功能
package com.kxg.file; import java.io.File; import java.io.IOException; /* * File类的判断功能: * public boolean isDirectory():是否是一个目录 * public boolean isFile():是否是一个标准文件 * public boolean exists():文件或目录是否存在 * public boolean canRead():是否可以读取 * public boolean canWrite():是否可以写入 * public boolean isHidden():是否隐藏 * */ public class FileDemo4 { public static void main(String[] args) throws IOException { File f = new File("xiao.pdf"); f.createNewFile(); System.out.println(f.isDirectory()); System.out.println(f.isFile()); System.out.println(f.exists()); System.out.println(f.canRead()); System.out.println(f.canWrite()); System.out.println(f.isHidden()); } }
获取功能
package com.kxg.file; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; /* * File类的获取功能: * public File getAbsoluteFile():获取绝对路径 * public String getPath():获取相对路径 * public String getName():获取名称 * public long length():获取长度(字节数) * public long lastModified():最后修改时间(毫秒值) * */ public class FileDemo5 { public static void main(String[] args) throws IOException { File f = new File("xiao.jpg"); // public File getAbsoluteFile():获取绝对路径 System.out.println(f.getAbsolutePath()); // public String getPath():获取相对路径 System.out.println(f.getParent()); // public String getName() System.out.println(f.getName()); // public long length() System.out.println(f.length()); // public long lastModified() Date d = new Date(f.lastModified()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(sdf.format(d)); } }
高级获取功能
package com.kxg.file; import java.io.File; /* * File类的高级获取功能: * public String[] list():获取指定目录下的所有文件和文件夹的名称数组 * public File[] listFiles():获取指定目录下的所有文件和文件夹的File对象数组 */ public class FileDemo6 { public static void main(String[] args) { // 封装目录 File f = new File("D://Test"); // 得到此目录下所有文件夹和文件的名称数组 String[] arr = f.list(); // 遍历得到每个文件夹和文件的名称字符串 for (String s : arr) { System.out.println(s); } System.out.println("==============="); // 得到此目录下所有文件夹和文件的File对象数组 File[] arr2 = f.listFiles(); // 遍历File数组 for (File name : arr2) { System.out.println(name.getName()); } } }
文件相关操作
得到指定目录下指定格式的文件方案1:
package com.kxg.file; import java.io.File; /* * 需求:判断D盘下Test文件夹下是否有.txt结尾的文件 */ public class FileDemo7 { public static void main(String[] args) { // 封装D:\Test目录 File f = new File("D:\\Test"); // 得到此目录下所有的文件和文件夹对象 File[] arr = f.listFiles(); // 遍历得到所有的File对象 for (File file : arr) { // 判断对象是否是文件 if (file.isFile()) { // 如果是文件,就得到文件名判断是不是以.txt结尾 if (file.getName().endsWith(".txt")) { // 如果是就输出文件名 System.out.println(file.getName()); } } } } }
方案2:过滤器
package com.kxg.file; import java.io.File; import java.io.FilenameFilter; /* * FilenameFilter接口:实现此接口的类实例可用于过滤器文件名 * public String[] list(FilenameFilter filter):获取符合过滤器的文件名数组 * public File[] listFiles(FilenameFilter filter):获取符合过滤器的文件对象数组 */ public class FileDemo8 { public static void main(String[] args) { // 封装D:\Test目录 File f = new File("D:\\Test"); // 得到此目录下所有的文件和文件夹对象 File[] arr = f.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { // System.out.println(dir + "..." + name); // 输出参数中的dir和name得知,dir是目录,name是文件夹和文件名 // 通过File的构造方法得到所有的f对象 File f = new File(dir, name); // 判断是否文件 boolean flag = f.isFile(); // 判断是否以.txt结尾 boolean flag2 = f.getName().endsWith(".txt"); // 综合前面两个的结果,如果是true就加入到数组中去 boolean flag3 = flag && flag2; return flag3; // 可以简化为:return new File(dir, name).isFile() && // name.endsWith(".txt"); } }); // 遍历得到所有的File对象 for (File file : arr) { System.out.println(file.getName()); } } }
批量修改同一格式文件的文件名:(这些文件名需要有规律)
package com.kxg.file; import java.io.File; /* * 需求:把D:\Test\四大名著目下 * 001_Hello_world_请修改我_西游记.txt * 002_Hello_world_请修改我_三国演义.txt * 003_Hello_world_请修改我_水浒传.txt * 004_Hello_world_请修改我_红楼梦.txt * 改为: * 001_西游记.txt * 002_三国演义.txt * 003_水浒传.txt * 004_红楼梦.txt */ public class FileDemo9 { public static void main(String[] args) { // 封装目录 File file = new File("D:\\Test\\四大名著\\"); // 获取文件对象数组 File[] arr = file.listFiles(); // 遍历所有对象 for (File f : arr) { // 获取每个文件的名字 String name = f.getName(); // 查找第一个_的索引,并从开始截取到次索引处获取前面的001,002,003,004 int start = name.indexOf("_"); String startName = name.substring(0, start); // 可以简化为 String start = name.substring(0, name.indexOf("_")); // 查找最后一个_的索引,并以这个索引为开始,截取到字符串末尾。得到_和四大名著名称。 int end = name.lastIndexOf("_"); String endName = name.substring(end); // 可以简化为 String end = name.substring(name.lastIndexOf("_")); // 把截取好的两个字符串拼接起来,就是需要改的文件名称。 String newName = startName.concat(endName); // 把新的名称封装成File对象,千万不要忘记加上前面的目录。 File newFile = new File(file, newName); // 给每个File对象重命名 f.renameTo(newFile); System.out.println(f.getName()); } } }
获取指定目录下所有格式或指定格式的文件:
package com.kxg; import java.io.File; /* * 需求:递归求出D:\Demo目录下所有.java文件 */ public class FilePathDemo { public static void main(String[] args) { // 封装目录 File file = new File("D:\\Demo"); getAllJava(file); } private static void getAllJava(File file) { // 得到全部文件夹和文件的File数组 File[] fileArray = file.listFiles(); // 遍历所有的File对象 for (File f : fileArray) { // 判断是否为文件夹 if (f.isDirectory()) { // 是文件夹就把这个File对象重新传入到这个方法中 // 继续得到这个文件夹中的全部文件夹和文件的File对象 getAllJava(f); // 除了文件夹就是文件,得到File对象的名字判断是否以.java结尾,是就输出绝对路径 } else if (f.getName().endsWith(".java")) { System.out.println(f.getAbsolutePath()); } } } }
删除文件夹(带内容):
package com.kxg; import java.io.File; /* * 需求:删除指定目录(带内容) */ public class FileDeleteDemo { public static void main(String[] args) { // 删除Test2文件夹 File file = new File("D:\\Test\\Test2"); delete(file); } private static void delete(File file) { // 得到目录下文件夹和文件的File对象 File[] fileArray = file.listFiles(); // 遍历File对象 for (File f : fileArray) { System.out.println(f.getName()); // 判断是否为文件夹 if (f.isDirectory()) { // 是就作为对象重新传入 delete(f); // 不是就删除并打印出删除文件的名字 } else { System.out.println(f.getName() + "====" + f.delete()); } } // 删除完所有的文件以后只留下空的文件夹,当空文件夹作为File对象传入时就可以直接删除了 System.out.println(file.getName() + "===" + file.delete()); } }
清空指定文件夹内容:
package com.kxg; import java.io.File; /* * 需求:删除带指定目录(带内容) */ public class FileDeleteDemo2 { static String s = "D:\\Test\\Test2"; public static void main(String[] args) { // 删除Test2文件夹 File file = new File(s); delete(file); } private static void delete(File file) { // 得到目录下文件夹和文件的File对象 File[] fileArray = file.listFiles(); if (fileArray != null) // 遍历File对象 for (File f : fileArray) { // 判断是否为文件夹 if (f.isDirectory()) { // 是就作为对象重新传入 delete(f); // 不是就删除并打印出删除文件的名字 } else { System.out.println(f.getName() + "====" + f.delete()); } } // 删除完所有的文件以后只留下空的文件夹,当空文件夹作为File对象传入时就可以直接删除了 if (!s.endsWith(file.getAbsolutePath())) System.out.println(file.getName() + "===" + file.delete()); } }
字节流
IO流分类:(默认情况按照数据类型分)流向:(以java程序为参照物)
输入流:读取数据
输出流:写入数据
数据类型:
字节流
字节输入流:
读取数据:InputStream
字节输出流:
写入数据:OutputStream
字符流
字符输入流:
读取数据:Reader
字符输出流:
写入数据:Writer
用系统自带的笔记本打开,读得懂的可以用字符流,读不懂就只能用字节流。
创建字节流对象
package com.kxg.IO; import java.io.FileOutputStream; import java.io.IOException; /* 1. 需求:往一个.txt文件里面写入hello,worle 2. 3. 往文件里面写入数据用OutputStreamhen 4. 因为OutputStreamhen是抽象类,所以要用它的子类FileOutputStream */ public class FileInputStreamDemo { public static void main(String[] args) throws IOException { // 创建字节流对象 FileOutputStream fos = new FileOutputStream("a.txt"); // 调用write()方法 fos.write("hello,world".getBytes()); // 释放资源 fos.close(); } }
创建字节流对象一共做了三件事:
如果a.txt文件不存在,就创建一个a.txt文件
创建fos对象
把fos对象指向a.txt文件
write()方法:
public void write(byte[] b)throws IOException
public void write(byte[] b,int off,int len)throwsIOException
public abstract void write(int b)throws IOException
如果write()方法需要传入的是字节数组,把需要传入的字符串转为字节数组传入就行。
close():释放资源
让流对象变成垃圾,可以被垃圾回收器回收
通知系统释放跟该文件相关的资源
package com.kxg.IO; import java.io.FileOutputStream; import java.io.IOException; /* * write()方法: * public abstract void write(int b):写一个字节 * public void write(byte[] b):写一个字节数组 * public void write(byte[] b,int off,int len):写一个字节数组的一部分 */ public class WriteDemo { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("a.txt"); fos.write(97);// 97底层二进制数据,通过记事本打开,记事本找到97对应的字符值就是a fos.write("hello,java".getBytes()); byte[] by = { 97, 98, 99, 100 }; fos.write(by, 0, 2);// 包前不包后,包含0不包含2 fos.close(); } }
数据换行和追加写入
package com.kxg.IO; import java.io.FileOutputStream; import java.io.IOException; import java.util.Scanner; /* * 需求:数据换行以及追加写入 */ public class WriteDemo2 { public static void main(String[] args) throws IOException { // 构造方法的可以实现追加写入 FileOutputStream fos = new FileOutputStream("a.txt", true); Scanner sc = new Scanner(System.in); System.out.println("输入内容:"); String s = sc.nextLine(); fos.write(s.getBytes()); fos.write("\r\n".getBytes()); fos.close(); } }
数据换行:
不同的系统识别不同的换行符号
windows:\r\n
linux:\n
MAC:\R
常见的高级记事本所有的都可以识别。
数据追加写入:
利用构造方法可以实现数据追加写入,没运行一次就写入一次。
读取数据
package com.kxg.IO; import java.io.FileInputStream; import java.io.IOException; /* * 读取数据: * 字节输入流 * 创建字节输入流对象 * 用read()方法,把结果显示在控制台 * 释放资源 * * read()方法: * public int read():一次读一个字节 * public int read(byte[] b):一次对一个字节数组 * public int read(byte[] b,int off,int len):一次对一个字节数组的一部分 */ public class ReadDemo { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("a.txt"); // 第一次读取 // int i = fis.read(); // System.out.println(i); // System.out.println((char) i);//返回的是int类型的值,需要强制转换为char // // 第二次读取 // i = fis.read(); // System.out.println(i); // System.out.println((char) i); // System.out.println("==================="); // while循环改进 int by = 0;// 初始化变量 // 读取到最后再往后读就是-1,不等于-1的时候全打印出来 while ((by = fis.read()) != -1) { System.out.print((char) by); } // 释放资源 fis.close(); } }
复制内容(1)
package com.kxg.IO; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 需求:把指定文件内容复制到指定文件里面去。 * * 数据源: * a.txt --读取 --FileInputStream * * 目的地: * b.txt --写入 --FileOutputStream */ public class CopyDemo2 { public static void main(String[] args) throws IOException { // 封装数据源 FileInputStream fis = new FileInputStream("a.txt"); FileInputStream fis2 = new FileInputStream("D:\\Test\\a.txt"); // 封装目的地 FileOutputStream fos = new FileOutputStream("b.txt"); FileOutputStream fos2 = new FileOutputStream("D:\\Test\\Test2\\b.txt"); int i = 0; while ((i = fis.read()) != -1) { fos.write(i); } while ((i = fis2.read()) != -1) { fos2.write(i); } fis.close(); fos.close(); fis2.close(); fos2.close(); } }
汉字的存储
package com.kxg.IO; import java.util.Arrays; /* * 计算机中汉字存储: * 一个汉字分为两个字节 * 第一个字节肯定是负数 * 第二个字节常见是负数,可能是正数,然并卵。 */ public class HanZiDemo { public static void main(String[] args) { String s = "汉字"; byte[] by = s.getBytes(); System.out.println(Arrays.toString(by)); } }
复制内容(2)
package com.kxg.IO; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 需求:一次读取一个字节数组复制文件 * */ public class CopyDemo4 { public static void main(String[] args) throws IOException { // 封装数据源 FileInputStream fis = new FileInputStream("a.txt"); FileInputStream fis2 = new FileInputStream("D:\\Test\\a.txt"); // 封装目的地 FileOutputStream fos = new FileOutputStream("b.txt"); FileOutputStream fos2 = new FileOutputStream("D:\\Test\\Test2\\b.txt"); byte[] by = new byte[1024]; int i = 0; while ((i = fis.read(by)) != -1) { fos.write(by, 0, i); } while ((i = fis2.read(by)) != -1) { fos2.write(by, 0, i); } fis.close(); fos.close(); fis2.close(); fos2.close(); } }
字节缓冲区流
package com.kxg.Buffer; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 缓冲区类(高效类): * * BufferedInputStream类:读 * public BufferedInputStream(InputStream in): * BufferedOuputStream类:写 * public BufferedOutputStream(OutputStream out): * 构造方法参数问题: * 字节缓冲区流仅仅提供缓冲区,为高效而设计,真正做读写操作的还是基本的流对象实现。 */ public class BufferDemo { public static void main(String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream( "a.txt")); BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("b.txt")); // int i; // while ((i = bis.read()) != -1) { // bos.write(i); // } byte[] by = new byte[1024]; int len=0; while ((len = bis.read(by)) != -1) { bos.write(by); } bis.close(); bos.close(); } }
字符流
通过一个转换流把字节流转换成字节流+编码表常见编码表:
ACSII表:7位表示一个数据,最高位为符号位。
ISO-8859-1:拉丁码表,8位表示一个数据。
BIG5:通行于台湾,香港地区的繁体字编码表。俗称“大五码”
UTF-8:最多用三个字节来表示一个字符。能用一个就用一个,现在不行就用三个。
转换流
package com.kxg.zifu; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; /* * OutputStreamWriter:字符输出流 * public OutputStreamWriter(OutputStream out):根据默认编码表把字节流的数据转换为字符流 * public OutputStreamWriter(OutputStream out,Charset cs):根据指定编码表把字节流的数据转换为字符流 * * InputStreamReader:字符输入流 * public InputStreamReader(InputStream in):根据默认编码表把字节流的数据转换为字符流 * public InputStreamReader(InputStream in,Charset cs):根据指定编码表把字节流的数据转换为字符流 * */ public class ZiFu { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(new FileInputStream( "a.txt")); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream( "b.txt")); int i = 0; while ((i = isr.read()) != -1) { osw.write(i); } osw.flush(); osw.close(); isr.close(); } }
默认的编码表跟随系统,系统为简体中文,默认的编码表就为简体中文。
flush()和close()的区别:
flush():刷新缓冲区,刷新之后流对象还可以继续使用。
close():关闭流对象之前会刷新一次缓冲区,关闭之后流对象就不能继续使用。
FileWriter&FileReader
package com.kxg.zifu; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* * 由于转换流的名称过长,Java提供了其子类供我们使用。 * OutputStreamWriter = FileOutputStream + 编码表 * FileWriter = FileOutputStream + 编码表 */ public class ZiFuDemo { public static void main(String[] args) throws IOException { // public FileReader(String fileName) // 构造方法中可以直接给一个路径或者文件名 FileReader fr = new FileReader("a.txt"); FileWriter fw = new FileWriter("b.txt"); FileReader fr2 = new FileReader("a.txt"); FileWriter fw2 = new FileWriter("c.txt"); int i = 0; while ((i = fr.read()) != -1) { fw.write(i); } char[] chs = new char[1024]; int len = 0; while ((len = fr2.read(chs)) != -1) { fw2.write(chs); } fr.close(); fw.close(); fw2.close(); } }
高效字符流
package com.kxg.zifu; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class ZiFuDemo2 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("a.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt")); BufferedReader br2 = new BufferedReader(new FileReader("a.txt")); BufferedWriter bw2 = new BufferedWriter(new FileWriter("c.txt")); int i = 0; while ((i = br.read()) != -1) { bw.write(i); } char[] chs = new char[1024]; int len = 0; while ((len = br2.read(chs)) != -1) { bw2.write(chs); } br.close(); bw.close(); br2.close(); bw2.close(); } }
高效字符流的特殊功能
可以一次读写一行package com.kxg.zifu; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class ZiFuDemo3 { public static void main(String[] args) throws IOException { write(); read(); } private static void write() throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt")); for (int x = 0; x < 10; x++) { bw.write("hello" + x); bw.newLine();// 写入一个行分隔符,也就是换行 bw.flush(); } bw.close(); } private static void read() throws IOException { BufferedReader br = new BufferedReader(new FileReader("a.txt")); String line = null; // readLine()方法读取到换行就结束了,打印的时候就要自己加换行。 while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); } }
字符流的五种读写方式
package com.kxg.zifu; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class ZiFuDemo4 { public static void main(String[] args) throws IOException { String srcString = "a.txt"; String destString1 = "1.txt"; String destString2 = "2.txt"; String destString3 = "3.txt"; String destString4 = "4.txt"; String destString5 = "5.txt"; method1(srcString, destString1); method2(srcString, destString2); method3(srcString, destString3); method4(srcString, destString4); method5(srcString, destString5); } private static void method5(String srcString, String destString) throws IOException { BufferedReader br = new BufferedReader(new FileReader(srcString)); BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); String line = null; while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); bw.flush(); } br.close(); bw.close(); } private static void method4(String srcString, String destString) throws IOException { // 高效流一次读取一个字符数组 BufferedReader br = new BufferedReader(new FileReader(srcString)); BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); char[] chs = new char[1024]; int len = 0; while ((len = br.read(chs)) != -1) { bw.write(chs); } br.close(); bw.close(); } private static void method3(String srcString, String destString) throws IOException { // 高效流一次读写一个字符 BufferedReader br = new BufferedReader(new FileReader(srcString)); BufferedWriter bw = new BufferedWriter(new FileWriter(destString)); int i = 0; while ((i = br.read()) != -1) { bw.write(i); } br.close(); bw.close(); } private static void method2(String srcString, String destString) throws IOException { // 一次读写一个字符数组 FileReader fr = new FileReader(srcString); FileWriter fw = new FileWriter(destString); char[] chs = new char[1024]; int len = 0; while ((len = fr.read(chs)) != -1) { fw.write(chs, 0, len); } fr.close(); fw.close(); } private static void method1(String srcString, String destString) throws IOException { // 一次读写一个字符 FileReader fr = new FileReader(srcString); FileWriter fw = new FileWriter(destString); int i = 0; while ((i = fr.read()) != -1) { fw.write(i); } fr.close(); fw.close(); } }
数据输入输出流
package com.kxg_01; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; /* * 数据输入流: * DataInputStream * 数据输出流: * DataOutputStream * * 可以写入任意类型的数据,也可以读取任意类型的数据。 */ public class DataInputStreamDemo { public static void main(String[] args) throws IOException { // 数据输出流 DataOutputStream dos = new DataOutputStream(new FileOutputStream( "a.txt")); // 数据输入流 DataInputStream dis = new DataInputStream(new FileInputStream("a.txt")); // 添加数据 dos.writeBoolean(true); dos.writeLong(123456789123456789L); dos.writeFloat(12.21F); dos.writeDouble(45.67); // 读取数据 System.out.println(dis.readBoolean()); System.out.println(dis.readLong()); System.out.println(dis.readFloat()); System.out.println(dis.readDouble()); dos.close(); dis.close(); } }
合并流
合并流读写两个文件package com.kxg_01; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; /* * 合并流: * SequenceInputStream * * 合并流读写两个文件 * 将a.txt和b.txt的内容写入到c.txt */ public class SequenceDemo { public static void main(String[] args) throws IOException { // 封装两个数据源 InputStream is = new FileInputStream("a.txt"); InputStream os = new FileInputStream("b.txt"); // 创建合并流对象 SequenceInputStream sis = new SequenceInputStream(is, os); // 封装目的地 BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("c.txt")); int i = 0; while ((i = sis.read()) != -1) { bos.write(i); } bos.close(); sis.close(); } }
合并流读写多个文件
package com.kxg_01; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.util.Enumeration; import java.util.Vector; /* * 合并流读写多个文件 * 将a.txt,b.txt,c.txt的内容写入到copy.txt */ public class SequenceDemo2 { public static void main(String[] args) throws IOException { // SequenceInputStream(Enumeration<? extends InputStream>e) // 通过此构造方法可以读写多个文件,可以看出需要Enumeration类型的参数 // Enumeration是Vector中elements()方法的返回值类型 // 创建Vector集合 Vector<InputStream> v = new Vector<InputStream>(); // 封装数据源 InputStream is1 = new FileInputStream("a.txt"); InputStream is2 = new FileInputStream("b.txt"); InputStream is3 = new FileInputStream("c.txt"); // 添加到集合中 v.add(is1); v.add(is2); v.add(is3); // 由集合方法elements()得到Enumeration类型数据 Enumeration<InputStream> e = v.elements(); // 创建合并流对象 SequenceInputStream sis = new SequenceInputStream(e); // 封装目的地 BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream("copy.txt")); int i = 0; while ((i = sis.read()) != -1) { bos.write(i); } sis.close(); bos.close(); } }
序列化和反序列化流
package com.kxg_02; import java.io.EOFException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; /* * 序列化流:把对象按照流一样的方式存入文本文件或者网络中传输。 对象--流数据(ObjectOutputStream) * 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据--对象(ObjectInputStream) */ public class ObjectStreamDemo { public static void main(String[] args) throws IOException, ClassNotFoundException { write(); read(); } private static void read() throws IOException, ClassNotFoundException { // 创建反序列化流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream( "oos.txt")); try { // 不知道要运行几次用while,最后会报一个EOFException的错误,自己做一下处理就行。 while(true) { Object obj = ois.readObject(); System.out.println(obj); } } catch (EOFException e) { System.out.println("反序列化结束!"); } } private static void write() throws IOException { // 创建序列化流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream( "oos.txt")); // 创建对象 Person p1 = new Person("李延旭", 20); Person p2 = new Person("任兴亚", 23); Person p3 = new Person("赵磊", 20); Person p4 = new Person("王澳", 21); // 把对象添加到流中 oos.writeObject(p1); oos.writeObject(p2); oos.writeObject(p3); oos.writeObject(p4); oos.close(); } }
对象类:
Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常
package com.kxg_02; import java.io.Serializable; /* * 需要进行序列化和反序列化的类必须实现Serializable接口 * 该接口没有任何方法,类似于这种没有方法的接口被称为标记接口 * * 类还需要添加一个serialVersionUID */ public class Person implements Serializable { /** * */ private static final long serialVersionUID = 1L; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } }
使用transient关键字修饰的成员变量就不能进行序列化
Properties类
属性集合类,是一个可以和IO流相结合使用的集合类,可保存在流中或从流中加载,属性列表中每个键及其值都是一个字符串。package com.kxg_03; import java.util.Properties; import java.util.Set; /* * Properties:属性集合类,是一个可以和IO流相结合使用的集合类, * 可保存在流中或从流中加载,属性列表中每个键及其值都是一个字符串。 */ public class PropertiesDemo { public static void main(String[] args) { // 当作Map集合来用 Properties p = new Properties(); // 添加元素,利用父类Hashtable的put()方法 p.put("李延旭", "20"); p.put("任兴亚", "23"); p.put("赵磊", "20"); // 遍历集合键值对元素 Set<Object> keys = p.keySet(); for (Object key : keys) { Object value = p.get(key); System.out.println(key + ":" + value); } } }
Properties特殊功能
package com.kxg_03; import java.util.Properties; import java.util.Set; /* * Properties特殊功能: * public Object setProperty(String key,String value):添加元素 * public String getProperty(String key):根据键获取值 * public Set<String> stringPropertyNames(): 获取键集 */ public class PropertiesDemo2 { public static void main(String[] args) { // 创建对象 Properties p = new Properties(); // 添加元素 p.setProperty("李延旭", "20"); p.setProperty("任兴亚", "23"); p.setProperty("赵磊", "20"); // 遍历集合 Set<String> keys = p.stringPropertyNames(); for (String key : keys) { String value = p.getProperty(key); System.out.println(key + ":" + value); } } }
Properties的load()和store()方法
package com.kxg_03; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; import java.util.Properties; import java.util.Set; /* * Properties的load()和store()方法。 * public void load(InputStream inStream): * public void load(Reader reader) * * public void store(OutputStream out, String comments):集合中的数据存储到文件,comments是属性列表的描述 * public void store(Writer writer,String comments) * * 注意: * 文件的数据必须是键值对形式的。 */ public class PropertiesDemo3 { public static void main(String[] args) throws IOException { loadDemo(); storeDemo(); } private static void storeDemo() throws IOException { // 创建集合对象 Properties p = new Properties(); // 添加元素 p.setProperty("李延旭", "20"); p.setProperty("任兴亚", "23"); p.setProperty("赵磊", "20"); // 集合中的数据存储到文件 Writer w = new FileWriter("a.txt"); p.store(w, "513"); w.close(); } private static void loadDemo() throws IOException { // 创建集合对象 Properties p = new Properties(); Reader r = new FileReader("a.txt"); // 文件中的数据读取到集合中 p.load(r); // 遍历集合 Set<String> keys = p.stringPropertyNames(); for (String key : keys) { String value = p.getProperty(key); System.out.println(key + ":" + value); } r.close(); } }
总结
学习IO流,首先要明白需要用什么流来操作指定文件,对于字节流和字符流应该熟练的掌握。在所有的流操作里。字节流是最基础的。任何基于字节的操作都是正确的。无论你是文本文件还是二进制的文件。相关文章推荐
- 20个高级面试总结
- 程序员技术练级攻略
- 程序员需要具备的基本技能
- 程序员头条
- 字符串操作——面试题总结
- 面试--问题总结--持续更新--放飞求职梦--2016校招
- 笔试面试错题集1
- 程序员面试必备锦囊,懂了这些工资轻松过万
- 百度2016届网页搜索面试题 队列单链表的实现(队列大小有限制)
- 网友整理的Android面试题集-附网友提供的参考答案
- 女程序员获得成功的技巧
- 要做Java程序员 需要知道那些技术 重点有那些
- 黑马程序员——java复习总结——其他类和IO流
- 黑马程序员--Java集合框架(3)
- Android面试过程描述
- android面试经验谈
- 笔试面试知识点转载
- 黑马程序员--java技术blog---第十一篇:反射
- Android面试题精选,自己收藏下
- 黑马程序员--Java多线程