JAVAEE笔记——IO流
目录
创建文件(夹),删除文件,移动(重命名)文件,打印分隔符
//1参构造方法 // File haha = new File("D://1.txt"); // boolean flag = haha.createNewFile(); //创建文件 // System.out.println(flag?"创建成功":"创建失败"); //通过创建文件夹创建文件 File dir = new File("D://haha"); //dir.mkdirs();//创建文件夹 //2.两参构造方法 File a = new File(dir,"a.txt"); a.createNewFile(); File b = new File(dir,"b.txt"); b.createNewFile(); //创建文件 //文件删除 a.delete(); b.delete(); //移动(重命名)文件 File file = new File("D://la.zip"); File newfile = new File("E://垃圾.zip"); file.renameTo(newfile); //打印当前操作系统的分隔符 System.out.println(File.pathSeparator); //路径分隔符 System.out.println(File.separator);//名称分隔符
文件遍历
public static void main(String[] args) { File e = new File("D:\\"); File[] files = e.listFiles(); listFile(files); } public static void listFile(File[] files) { if (files != null && files.length > 0) { for (File file : files) { if (file.isFile()) {//找到文件 if (file.getName().endsWith(".avi")) { //找到一个.avi为后缀的文件 if (file.length() > 10 * 1024 * 1024) { //打印大于10MB的文件 System.out.println("找到了一个avi文件:" + file.getAbsolutePath()); } } } else {//找到文件夹 File[] files2 = file.listFiles(); // 再取文件夹里的所有子文件 listFile(files2); //递归遍历,判断是文件还是文件夹。 } } } }
文件过滤
public static void main(String[] args) { File e = new File("e:\\"); listFiles(e); } public static void listFiles(File file){ //1.创建一个过滤器,并描述规则 FileFilter filter = new AVIFileFilter(); // 2.通过文件获取子文件夹 File[] files = file.listFiles(filter); //listFiles:获取文件列表 if (files!=null&&files.length>0) { for (File f : files) { if (f.isDirectory()) { listFiles(f); //继续处理文件夹 } else { System.out.println("发现一个avi:" + f.getAbsolutePath()); } } } } /** * 文件过滤器 */ static class AVIFileFilter implements FileFilter { @Override public boolean accept(File pathname) { if (pathname.getName().endsWith(".avi")||pathname.isDirectory()){ return true; //表示保留 } return false; //表示不保留 } }
相对路径和绝对路径
-
绝对路径:从盘符开始,是一个完整的路径,例如:c://a.txt
-
相对路径:在java代码中是相对于项目目录路径,这是一个不完整的便捷路径,在java开发中很常用.例如:a.txt
IO流概述
-
可以将这种数据传输操作(从C盘拷贝文件到D盘),看做一种数据的流动,按照流动的方向分为输入Input和输出Output。
-
Java中的IO操作主要指的是java.io包下的一些常用类的使用
-
IO流的分类:
-
按照流的方向来分:可以分为输入流和输出流
-
按照流动的数据类型来分,可以分为:字节流和字符流
-
字节流
-
输入流:*父类InputStream
-
输出流:*父类OutputStream
-
-
字符流
-
输入流:*父类Reader
-
输出流:*父类Writer
-
-
-
-
一切皆字节:
-
计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的。
-
在数据传输时,也都是二进制的形式存储的。
-
后续学习的任何流,在传输时底层都是二进制。
-
OputStream的方法
FileOputStream的方法
FileInputStream的方法
构造方法
常用方法
原因:实际上这个byte数组,都是同一个数组,而新写的内容是覆盖原来内容的位置
read()方法
//InputStream FileInputStream fis = new FileInputStream("D://1.txt"); //创建流 /* //这种方法不常用 while (true){ byte b = (byte)fis.read(); //read():从输入流中读取一个字节的数据。 if (b==-1){ break; }*/ //这种一次读取一组内容的方式更为常用,基本不用每次读取一个字节的方式 //文件写入的内容为26个英文字母 byte[] bytes = new byte[10]; int len =fis.read(bytes);//10 //read(数组b)从:此输入流 b.length最多 b.length字节的数据读 b.length字节数组。 System.out.println(new String(bytes,0,len));//把数组bytes转为字符串,从0开始读取,读取len个长度的内容 len = fis.read(bytes);//10 System.out.println(new String(bytes,0,len)); len = fis.read(bytes);//6 System.out.println(new String(bytes,0,len)); len = fis.read(bytes);//没有内容了,读取的长度应为-1 System.out.println(len); fis.close(); }
机械硬盘的优点:能够长时间(几十年)存储,长时间掉电也不会丢失数据。耐高低温。通过指针来读写数据,指针转动速度越快,声音越大。
固态硬盘: 读写快,但不耐高温。高温或者长时间储存,数据会丢失。
字节流读取文字
//InputStream FileInputStream fis = new FileInputStream("b.txt"); //创建流 /*while (true){ byte b = (byte)fis.read(); //read():从输入流中读取一个字节的数据。 if (b==-1){ break; }*/ //这种一次读取一组内容的方式更为常用,基本不用每次读取一个字节的方式 //文件写入的内容为26个英文字母 byte[] bytes = new byte[10]; int len =fis.read(bytes);//10 //read(数组b)从:此输入流 b.length最多 b.length字节的数据读 b.length字节数组。 System.out.println(new String(bytes,0,len));//把数组bytes转为字符串,从0开始读取,读取len个长度的内容 len = fis.read(bytes);//10 System.out.println(new String(bytes,0,len)); len = fis.read(bytes);//6 System.out.println(new String(bytes,0,len)); fis.close();
字符输出
Filewriter的构造方法
常用方法
//writer FileWriter fw = new FileWriter("D://b.txt",true);//true表示追加模式 //fw.write("锄禾日当午"); /*FileWriter fw2 = (FileWriter) fw.append("锄禾日当午");//append方法会返回一个调用对象 System.out.println(fw==fw2); //结果为True*/ //因此,我们可以连用append()方法 fw.append("锄禾日当午").append(",").append("谁知盘中餐"); fr.frush()//字符首先是存在缓存中,只有调用frush时才会将缓存中的字符输出到文件中。 fr.close();//每次调用close的时候,系统都会调用frush进行刷新。
字符读取
FileReader的构造方法
常用方法
FileReader fr = new FileReader("b.txt"); /* while (true){ int c = fr.read();//每次读取一个字符 if (c==-1){ break; } System.out.println((char)c); }*/ char[] chars = new char[100]; int len = fr.read(chars); //数组默认值为0,这样的操作能够保证打印字符的长度,而不把数组中剩余的0打印出来。 System.out.println(new String(chars,0,len)); fr.close();
操作字符输出流时记得使用flush
-
flush的作用:字符首先是存在缓存中,只有调用frush时才会将缓存中的字符输出到文件中。每次调用close的时候,系统都会调用frush进行刷新。
Print与BufferReader
//字符输出(打印流) PrintStream ps = new PrintStream("D://c.txt"); /*ps.println("锄禾日当午,汗滴禾下土"); ps.println("锄禾日当午,汗滴禾下土"); ps.println("锄禾日当午,汗滴禾下土");*/ /*PrintWriter pw = new PrintWriter("D://c.txt");//这是字符打印,在写入后需要使用flush来刷新缓存 pw.println("谁知盘中餐,粒粒皆辛苦"); pw.println("谁知盘中餐,粒粒皆辛苦"); pw.println("谁知盘中餐,粒粒皆辛苦"); pw.flush();*/ FileOutputStream fos = new FileOutputStream("D://c.txt");//字节流 PrintWriter pw = new PrintWriter(fos);//可以通过打印流将字节流转换为字符流 pw.println("锄禾日当午,汗滴禾下土哈哈哈"); pw.flush(); //缓存读取流,将字符输入流 转换为带有缓存 可以一次读取一行的缓存字符读取流 FileReader fw = new FileReader("D://c.txt"); //字符流 BufferedReader br = new BufferedReader(fw); String text = br.readLine();//readline():每次可以读取一行,读到一行的末尾时会返回null System.out.println(text);
收集异常日志
try { String s = null; s.toString(); } catch (Exception e){ PrintWriter pw = new PrintWriter("D://bug.txt"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); //格式化时间模版 pw.println(sdf.format(new Date())); //打印出错时间 e.printStackTrace(pw);//输出到文本中 pw.close(); }
Properties的储存和读取
//.properties文件与Properties类 /** * 储存 *//* Properties ppt = new Properties();// Properties类是一个hashtable类型,采用键值对的形式进行储存 ppt.put("name","金苹果"); ppt.put("图书简介","讲述了苹果种植的过程"); FileWriter fw = new FileWriter("D://book.properties");//必须以.properties为后缀名 ppt.store(fw,"存储了图书");//comments:对文件的注释 fw.close();*/ /** * 读取 */ Properties ppt = new Properties();//创建存储对象 Reader r = new FileReader("D://book.properties"); ppt.load(r); //采用map中的get方法来打印键值对 //或者采用properties的getProperties()方法来打印键值对 System.out.println(ppt.getProperty("name")); System.out.println(ppt.get("图书简介")); }
序列化与反序列化
序列化:将对象在内存中存储的字节序列,存储在文件的方式来实现存储对象。
反序列化:从文件中读取对象。
-
要序列化的类,必须implements 接口Serializable,否则会报错
-
Serializable接口没有任何内容,这种接口称其为标记接口。
-
其属性的类也必须implements Serializable,否则会报错。
try-with-source
//try-with-resources /* //1.7之前 *//** * try的()的方法必须能调用close方法,当程序调用完try或catch里面的语句后,就会自动调用close方法来关闭流 *//* try(FileReader fr = new FileReader("D://1.txt");) { int c = fr.read(); System.out.println((char)c); } catch (IOException e) { e.printStackTrace(); }*/ /*//JDK9进行了优化 FileReader fr = new FileReader("D://1.txt"); PrintWriter pw = new PrintWriter("D://1.txt"); try(fr;pw) { //同1.7的要求和功能一样,不过这里允许传递对象 int c = fr.read(); System.out.println((char)c); } catch (IOException e) { e.printStackTrace(); }*/ ClossDemo d = new ClossDemo(); try(d){ }catch (Exception e){ } } static class ClossDemo implements Closeable{ @Override public void close() throws IOException { System.out.println("close方法被调用了"); } }