6、I/O
一、File
1、File类的构造方法:
File(File parent, String child); // 根据父抽象路径和子路径创建文件对象 File(String pathname); // 指定文件路径创建文件对象 File file = new File("E:\\1.txt"); 并不是创建文件 File(String parent, String child) // 两部分构建
目录分隔符:Windows“\”(都可以使用,/只需要写一个),Linux是“/”,可以通过separator获取
2、常用方法:
1、创建
createNewFile();
(2)创建文件夹,只会创建最后一级文件夹,上级目录不存在就抛出异常
mkdir();
(3)创建多级文件夹,创建所有不存在的目录
mkdirs();
(4)目标文件与源文件是在同一目录下,就是重命名(文件和文件夹都行);不在则是剪切,而且不能操作文件夹
renameTo(File dest);
2、删除
(1)删除文件或文件夹
delete();
(2)JVM退出的时候删除文件,一般用于删除临时文件
deleteOnExit();
3、判断
(1)
exists();
(2)
isFile();
(3)
isDirectory();
(4)是否是隐藏文件或者隐藏目录
isHidden();
(5)
isAbsolute();
4、获取
(1)获取文件或文件夹名,不含上级路径
getName();
(2)返回绝对路径,也可以是相对路径,但是目录要指定
getPath();
(3)获取绝对路径,与文件存在没有关系
getAbsolutePath();
(4)获取文件大小,字节数
length();
(5)获取文件的父路径
getParent();
(6)最后一次修改时间
lastModified();
5、文件夹相关
(1)列出所有的根目录
listRoots();
(2)把当前文件夹下面的所有子文件名与子文件夹名(不包括孙)存储到一个String数组中返回
list();
(3)把当前文件夹下的所有子文件和子文件夹都使用一个File对象描述,然后把File对象存储到File数组中
listFiles();
(4)
list(FilenameFilter filter);
(5)自定义文件名过滤器
listFiles(FilenameFilter filter);
输入输出划分:
二、字节流
1、输入字节流:
注意:用缓冲数组读取效率更高
要是缓冲数组只有4时,每次读完数据第二次是覆盖到前面的数组
2、输出字节流
输出[-1, 0, 0, 0];255(11111111)以补码形式存在
拷贝图片
注意:每新创建一个FileOutputStream的时候,默认情况下FileOutputStream的指针指向文件开始位置,每写出一次指向都会相应移动(写的时候加不加true问题)
3、异常处理
4、缓冲输入字节流BufferedInputStream(其实跟自定义内存数组byte[] buf的原理一样,不常用 )
5、缓冲输出字节流BufferedOutputStream
bufferedInputStream.read()方法中,要是传入了buf缓冲数组返回值是存储到缓冲数组字节个数;要是没有传入,则返回的是读取到的内容
三、字符流
输入字符流(默认使用GBK编码表)
1、FileWriter输出字符流
写数据的时候,FileWriter内部维护了1024字节的数组,写数据的时候会先写到数组中,要写到硬盘上时,需要调用flush或者是close方法或者是填满内部字符数组
2、缓冲输入字符流(常用,比缓冲数组好,常用)BufferedReader
1 public static void testRead() throws IOException { 2 // 找到目标文件 3 File file = new File("E:\\eclipseProject\\Demo4\\src\\cn\\guojie\\file\\Demo7.java"); 4 // 建立数据传输通道 5 FileReader fileReader = new FileReader(file); 6 // 建立缓冲输入字符流 7 BufferedReader reader = new BufferedReader(fileReader); 8 // 读取数据 9 String line = null; 10 while((line = reader.readLine())!=null) { 11 System.out.println(line); 12 } 13 // 关闭资源 14 reader.close(); 15 }
1 // 自定义readLine方法,读一行 2 public static String myReadLine(FileReader fileReader) throws IOException { 3 StringBuilder sb = new StringBuilder(); 4 int content = 0; 5 while((content = fileReader.read())!=-1) { // 每次读一个字符,存在int中 6 if(content =='\r') { // \r回车忽略 7 continue; 8 } else if(content =='\n') { // \n跳出循环 9 break; 10 } else { 11 sb.append((char)content); // 整型强转为char 12 } 13 } 14 15 if(content==-1) { // 代表读完了 16 return null; 17 } 18 19 return sb.toString(); // StringBuilder转化为String 20 } 21 22 public static void testReader1() throws IOException { 23 // 找到目标文件 24 File file = new File("E:\\eclipseProject\\Demo4\\src\\cn\\guojie\\file\\Demo7.java"); 25 // 建立数据传输通道 26 FileReader fileReader = new FileReader(file); 27 // 读取数据 28 String line = null; 29 // !(line = myReadLine(fileReader)).equals("") // 用StringBuilder最少会返回空串"" 30 while((line = myReadLine(fileReader))!=null) { 31 System.out.println(line); 32 } 33 // 关闭通道 34 fileReader.close(); 35 }
3、缓冲输出字符流(提高FileWriter的读写效率和扩展功能)(常用) BufferedWriter
1 boolean isLogin = false; // 判断是否登录成功标识 2 while((line = bufferReader.readLine())!=null) { 3 if(info.equals(line)) { // 读一行,如果第一行不行接着往下读,如果用if else判断的成功话,会造成 4 // 读完一行之后不对会直接判断登录失败,应该用一个isLogin的变量判断是否登录成功 5 isLogin = true; 6 break; 7 } 8 } 9 10 if(isLogin) { // 此时通过标识判断是否登录成功 11 System.out.println("恭喜,登陆成功!"); 12 } else { 13 System.out.println("对不起,登录失败,请重新输入"); 14 }
四、装饰者设计模式
1 // 加;缓冲输入字符流 2 class BufferedSepetrator extends BufferedReader { // 继承是为了让装饰类对象可以作为参数传递,达到互相装饰的效果 3 // 在内部维护维护一个被装饰类的引用 4 BufferedReader bufferedReader; 5 6 public BufferedSepetrator(BufferedReader bufferedReader) { // new BufferdLineNum() 7 super(bufferedReader); 8 this.bufferedReader = bufferedReader; 9 } 10 11 public String readerLine() throws IOException { 12 String line = bufferedReader.readLine(); // 传入bufferedLineNum,使bufferedReader指 13 // 向子类BufferdLineNum,调用子类的readLine方法 14 if(line == null) { 15 return null; 16 } 17 line = line+";"; 18 19 return line; 20 } 21 }
1 public class Demo { 2 3 public static void main(String[] args) throws IOException { 4 File file = new File("E:\\eclipseProject\\Demo4\\src\\cn\\guojie\\file\\Demo7.java"); 5 FileReader fileReader = new FileReader(file); 6 BufferedReader bufferedReader = new BufferedReader(fileReader); 7 // 建立带行号的缓冲输入字符流 8 BufferdLineNum bufferedLineNum = new BufferdLineNum(bufferedReader); 9 // 建立带分号的缓冲输入字符流,传入bufferedLineNum,使父类引用类型指向子类对象从而调用子类的方法 10 BufferedSepetrator bufferedSeperator = new BufferedSepetrator(bufferedLineNum); 11 // 读缓冲流 12 String line = null; 13 while((line = bufferedSeperator.readerLine())!=null) { 14 System.out.println(line); 15 } 16 // 关闭资源 17 bufferedSeperator.close(); 18 } 19 20 }
五、序列流 SequenceInputStream
合并两个或多个流
常用方法
(1)合并两个输入流
SequenceInputStream(InputStream s1, InputStream s2);
(2)合并多个输入流,借助vector的element方法获得Enumation枚举对象传入
SequenceInputStream(Enumeration<? extends InputStream> e);
1 public static void merge1() throws IOException { 2 // 找到目标文件 3 File file1 = new File("E:\\a.txt"); 4 File file2 = new File("E:\\b.txt"); 5 File file3 = new File("E:\\c.txt"); 6 // 建立输入输出字节流 7 FileInputStream fileInputStream1 = new FileInputStream(file1); 8 FileInputStream fileInputStream2 = new FileInputStream(file2); 9 FileOutputStream fileOutputStream = new FileOutputStream(file3); 10 // 创建序列化流 11 SequenceInputStream sequenceInputStream = new SequenceInputStream(fileInputStream1, fileInputStream2); 12 // 读写数据 13 byte[] buf = new byte[1024]; 14 int length = 0; 15 while((length = sequenceInputStream.read(buf))!=-1) { 16 fileOutputStream.write(buf, 0, length); 17 } 18 // 关闭资源 19 sequenceInputStream.close(); // 调用FileInputStreamdeclose() 20 fileInputStream2.close(); 21 fileOutputStream.close(); 22 }
1 public static void merge2() throws IOException { 2 // 找到目标文件 3 File file1 = new File("E:\\a.txt"); 4 File file2 = new File("E:\\b.txt"); 5 File file3 = new File("E:\\c.txt"); 6 File file4 = new File("E:\\d.txt"); 7 // 建立输入输出字节流 8 FileInputStream fileInputStream1 = new FileInputStream(file1); 9 FileInputStream fileInputStream2 = new FileInputStream(file2); 10 FileInputStream fileInputStream3 = new FileInputStream(file3); 11 FileOutputStream fileOutputStream = new FileOutputStream(file4); 12 // 创建序列化流 13 Vector<FileInputStream> vector = new Vector<FileInputStream>(); 14 vector.add(fileInputStream1); 15 vector.add(fileInputStream2); 16 vector.add(fileInputStream3); 17 // 通过Vector获取迭代器 18 Enumeration<FileInputStream> e = vector.elements(); 19 20 SequenceInputStream sequenceInputStream = new SequenceInputStream(e); 21 byte[] buf = new byte[1024]; 22 int length = -1; 23 while((length = sequenceInputStream.read(buf))!=-1) { 24 fileOutputStream.write(buf, 0, length); 25 } 26 //关闭资源 27 sequenceInputStream.close(); 28 fileOutputStream.close(); 29 }
切割和合并mp3
// 切割mp3 public static void cutFile() throws IOException { // 找到目标文件 File file = new File("D:\\CloudMusic\\走在冷风中.mp3"); // 建立目标文件夹 File dir = new File("E:\\cutMusic"); // 建立输入输出流 FileInputStream fileInputStream = new FileInputStream(file); // 读写文件,以1M为单位切割 byte[] buf = new byte[1024 * 1024]; int length = 0; for (int i = 0; (length = fileInputStream.read(buf)) != -1; i++) { int num = i + 1; FileOutputStream fileOutputStream = new FileOutputStream(new File(dir, "part" + num + ".mp3")); fileOutputStream.write(buf, 0, length); // 关闭缓冲输出流 fileOutputStream.close(); } // 关闭资源 fileInputStream.close(); } // 合并mp3 public static void merge() throws IOException { // 找到目标文件 File dir = new File("E:\\cutMusic"); // 通过目标文件夹找到所有的mp3文件,然后把所有的mp3文件添加到Vector Vector<FileInputStream> vector = new Vector<FileInputStream>(); File[] files = dir.listFiles(); // 列出目标文件夹中所有的目标文件 for (File file : files) { if (file.getName().endsWith(".mp3")) { // 文件以.mp3结尾 vector.add(new FileInputStream(file)); // vector中需要传入FileInputStream } } // 通过Vector获取迭代器 Enumeration<FileInputStream> e = vector.elements(); // 创建序列流 SequenceInputStream sequenceInputStream = new SequenceInputStream(e); // 创建文件输出字节流 FileOutputStream fileOutputStream = new FileOutputStream("F:\\合并.mp3"); // 创建缓冲数组读写文件 byte[] buf = new byte[1024]; int length = 0; while ((length = sequenceInputStream.read(buf)) != -1) { fileOutputStream.write(buf, 0, length); } // 关闭资源 fileOutputStream.close(); sequenceInputStream.close(); }
六、序列化
注意细节:
1 // 序列化 2 public static void writeObj() throws IOException { 3 // 把User对象信息持久化存储 4 User user = new User("xiaoming", "123456"); 5 // 找到目标文件 6 File file = new File("E:\\Obj.txt"); 7 // 建立输出流对象 8 FileOutputStream fileOutputStream = new FileOutputStream(file); 9 // 建立对象的输出流对象 10 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); 11 // 写出对象 12 objectOutputStream.writeObject(user); 13 // 关闭资源 14 objectOutputStream.close(); 15 16 }
1 // 反序列化 2 public static void readObj() throws IOException, ClassNotFoundException { 3 // 找到目标文件 4 File file = new File("E:\\Obj.txt"); 5 // 建立输入流对象 6 FileInputStream fileInputStream = new FileInputStream(file); 7 // 建立对象的输入流对象 8 ObjectInputStream inputStream = new ObjectInputStream(fileInputStream); 9 // 读取文件信息 10 User readObject = (User) inputStream.readObject(); // 强转时可能产生ClassNotFoundException 11 System.out.println(readObject); 12 // 关闭文件 13 inputStream.close(); 14 }
七、配置文件类Properties(常用)
用于生成和读取配置文件的信息,属于Java.util的集合体系Map的类---> Hashtable
常用方法:
(1)添加Properties项,不用put(配置文件的键值都要求是字符串,put却可以任意添加类型数据)
setProperty(String key, String value);
(2)产生配置文件
store(Writer writer, String comments);
(3)加载配置文件
load(Reader reader);
1 // 保存配置文件的信息 2 public static void saveProperties() throws IOException { 3 // 创建Properties对象 4 Properties properties = new Properties(); 5 // 添加,不用put 6 properties.setProperty("张三", "123"); 7 properties.setProperty("李四", "456"); 8 properties.setProperty("王五", "789"); 9 // 遍历Properties 10 Set<Entry<Object,Object>> entrys = properties.entrySet(); 11 for(Entry<Object,Object> entry : entrys) { 12 System.out.println("键:"+entry.getKey()+"值:"+entry); 13 } 14 // 使用Properties产生配置文件,字符传FileWriter,字节传FileInputStream 15 properties.store(new FileWriter("E:\\a.properties"), "nihao"); // comments 16 }
1 // 读取配置文件 2 public static void readProperties() throws IOException { 3 // 创建Properties对象 4 Properties properties = new Properties(); 5 // 加载配置文件 6 properties.load(new FileReader("E:\\a.properties")); 7 // 遍历Properties 8 Set<Entry<Object,Object>> entrys = properties.entrySet(); 9 for(Entry<Object,Object> entry : entrys) { 10 System.out.println("键:"+entry.getKey()+"值:"+entry); 11 } 12 // 修改 13 properties.setProperty("张三", "aaa"); 14 // 修改完成后再保存配置文件 15 properties.store(new FileWriter("E:\\b.properties"), "修改之后"); 16 }
1 // 软件运行次数配置文件 2 public static void count() throws IOException { 3 // 找到目标文件 4 File file = new File("E:\\c.properties"); 5 if(!file.exists()) { // 目标文件不存在就创建 6 file.createNewFile(); 7 } 8 9 // 创建Properties对象 10 Properties properties = new Properties(); 11 // 加载配置文件到Properties中 12 properties.load(new FileReader(file)); 13 14 int count = 0; // 计数 15 String value = properties.getProperty("count"); // 从properties取出count 16 if(value!=null) { 17 count = Integer.parseInt(value); // String转换为整数 18 } 19 // 超过三次退出jvm 20 if(count==3) { 21 System.out.println("您已使用超过试用次数,请购买软件"); 22 System.exit(0); // 退出java虚拟机 23 } 24 25 count++; 26 27 System.out.println("已使用"+count+"次"); 28 // 添加properties项 29 properties.setProperty("count", count+""); 30 // 产生配资文件 31 properties.store(new FileOutputStream(file), "运行次数"); // new FileOutputStream(file)要放到load后,不然FileOutputStream每次会清空 32 }
八、打印流PrintStream
system.setOut();重新设置标准输出流对象
作用:
1 Exception e; 2 e.printStackTrace // 打印异常信息到控制台,会丢失一部分异常信息
1 // 收集异常日志信息 2 public static void exceptionLog() throws IOException { 3 // 创建打印流对象 4 PrintStream logPrintStream = new PrintStream(new FileOutputStream(new File("E:\\2015年11月29日.log"))); 5 try { 6 int[] a = null; 7 System.out.println(a.length); 8 9 int c = 4/0; 10 System.out.println(c); 11 12 } catch (Exception e) { 13 e.printStackTrace(logPrintStream); 14 } 15 }
九、编码和解码
十、转换流(常用)
作用:
1 // 使用输出字节转换流指定码表写数据 2 public static void writeTest() throws IOException { 3 // 把输出字节流转换成字符流并指定码表(读写的码表要一样) 4 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File("E:\\abc.txt")), "utf-8"); 5 // 使用输出字节转换流写数据 6 outputStreamWriter.write("你好"); 7 //关闭资源 8 outputStreamWriter.close(); 9 }
1 // 使用输入字节转换流指定码表读数据 2 public static void readTest() throws IOException { 3 // 把输入字节流转换成字符流并指定码表(读写的码表要一样) 4 InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(new File("E:\\abc.txt")), "utf-8"); 5 // 使用输入字节转换流读数据 6 char[] buf = new char[1024]; 7 int length = 0; 8 while((length = inputStreamReader.read(buf))!=-1) { 9 System.out.println(new String(buf, 0, length)); 10 } 11 // 关闭资源 12 inputStreamReader.close(); 13 }
十一、递归
1 // 递归文件夹的目录,列出子文件名和子文件夹名以及子文件夹下的孙文件名,先浅后深 2 public static void listFiles(File dir, String space) { 3 File[] files = dir.listFiles(); // 列出目录下所有文件名 4 for(File file : files) { 5 if(file.isFile()) { // 文件 6 System.out.println(space+file.getName()); // 列出文件名 7 } else if(file.isDirectory()) { // 目录 8 System.out.println(space+file.getName()); // 列出目录名 9 // 递归 10 listFiles(file, "| "+space); 11 } 12 } 13 }
1 // 递归删除文件夹及其下面的文件夹和文件 2 public static void deleteFiles(File dir) { 3 File[] files = dir.listFiles(); // 列出目录下所有文件名 4 for(File file : files) { 5 if(file.isFile()) { // 文件 6 file.delete(); // 删除文件 7 } else if(file.isDirectory()) { // 文件夹 8 deleteFiles(file); // 文件夹 9 } 10 } 11 dir.delete(); // 删除根目录 12 }