IO流
File类
文件和目录路径名的抽象表示形式
ps:File是操作文件的一种方式,需要传入一个路径,通过对当前路径的一个封装,
封装成一个File对象,通过File类中所提供的一些方法可以对路径下的文件进行操作
路径:
绝对路径--->是从盘符开始的路径 C:\text\demo.txt
相对路径--->不是盘符开始的路径 /text/demo.txt --> C:\
ps:相对路径需要有参考路径
千万不要做:在代码中创建对象--> File 参数的参数即可以是一个相对路径也可以是绝对路径
在程序中书写相对路径是有参考值,参考的是当前工程
/text/demo.txt 参考c:做不到的 --> 找不到文件路径 绝对路径
java是需要资源文件 --> 配置 图片 音频
将这些资源直接放到当前工程下这样的好处是 ,方便使用便于移植,应该使用相对路径
若将容量较大的文件放入到工程,就会将大文件挂载到服务器端,就会进行远程下载,然后匹配系统进行路径匹配
Unix:(收费的) 严格区分大小写的 使用"/"来分割路径(Linux)
Windows: 使用\来分割路径,因为\在java代码中代表转义,所以书写路径是就需要使用\\
ps:相对路径不需要 ,为了方便开发其实Winodws其实是支持/
"C:\\text\\demo.txt" --> C:/text/demo.txt
路径是不会自动添加\\ ,新版本4.7开始会自动添加\\
/** * */ package com.qfedu.Day19.File; import java.io.File; public class FileDemo1 { public static void main(String[] args) { String path = File.pathSeparator; char cpath = File.pathSeparatorChar; System.out.println("路径分割符:"+path); System.out.println("路径分割符:"+cpath); //正常来说要拼接路径就需要使用路径符号,但是拼接比较麻烦 String spath = File.separator; char ccpath = File.separatorChar; System.out.println("路径分割符:"+spath); System.out.println("路径分割符:"+ccpath); //C:\Program Files (x86)\alipay String pathStr = "C:"+File.separator+"Program Files (x86)"+File.separator+"alipay"; System.out.println(pathStr); } }
我们怎么知道在什么平台下使用什么路径呢?
可以使用File类中所提供的字段来区分
看FileDemo2
/** * */ package com.qfedu.Day19.File; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Date; public class FileDemo2 { public static void main(String[] args) throws IOException { FileMethod1(); FileMethod2(); FileMethod3(); FileMethod4(); } //File文件操作路径的方法 public static void FileMethod1() { //1.创建File对象 File f = new File("D:\\abc\\xxx\\123.txt"); //获取当前对象绝对路径 (路径方式考虑) System.out.println(f.getAbsolutePath()); //获取当前对象绝对路径 (文件/文件夹方式考虑) System.out.println(f.getAbsoluteFile()); //获取当前对象的文件路径 -->绝对路径是一样 //ps:若当前路径下是文件,建议使用getPath来获取 System.out.println(f.getPath()); //获取文件的名字 System.out.println(f.getName()); //获取父路径(路径方式考虑) System.out.println(f.getParent()); //获取父路径(文件/文件夹方式考虑) System.out.println(f.getParentFile()); } //如何检查当前文件的属性 public static void FileMethod2() { File f = new File("D:\\abc\\xxx\\123.txt"); //检查当前文件是不是一个可执行文件(在Windows中效果非常的明显,Linux) //可执行的文件.exe .dll(豆) System.out.println(f.canExecute()); //判断是不是可读 System.out.println(f.canRead()); //判断是不是可写 System.out.println(f.canWrite()); //获取文件最后的修改时间(毫秒值) -->转换 System.out.println(new Date(f.lastModified()).toLocaleString()); //获取文件的大小(单位是字节) System.out.println(f.length()); //盘当前文件是否是隐藏文件 System.out.println(f.isHidden()); } //文件对象的基本操作(文件) public static void FileMethod3() throws IOException { File dir = new File("D:\\abc\\xxx"); //同父子路径的拼接创建file对象 File f = new File(dir,"123.txt"); //File f = new File("D:\\abc\\xxx","123.txt"); //判断当前File对象是不是一个文件 System.out.println(f.isFile()); //判断当前File对象是不是一个文件夹 System.out.println(dir.isDirectory()); //删除文件/文件夹 --> true删除成功 false 删除失败 //System.out.println(f.delete()); //判断文件是否存在 //System.out.println(f.exists()); if(!f.exists()) { //文件不存在是真 存在了是假的 //创建文件 //io包--> IOException -->io包下一场的父类异常 f.createNewFile(); }else { //删除文件 f.delete(); //ps:在JVM停止时删除文件 //f.deleteOnExit(); } } //文件对象的基本操作(目录(文件夹)) public static void FileMethod4() { File f = new File("D:\\123\\456\\789\\11111"); //判断是不是文件夹 System.out.println(f.isDirectory()); //判断当前文件夹是否存在 System.out.println(f.exists()); //创建文件夹 -->mkdir必须背下来 --> Linux也是使用mkdir创建文件夹 //true 创建成功 false 创建失败 System.out.println(f.mkdir()); //多层级文件夹创建 //File f1 = new File("D:\\zhige\\ooo\\ppp\\xxx\\qqq"); //true 创建成功 false 创建失败 //System.out.println(f1.mkdirs()); //列出所有的文件名 File f1 = new File("D:\\baidu\\BaiduNetdisk"); String[] names = f1.list(); System.out.println(Arrays.toString(names)); //列出所有文件对象 File[] files = f1.listFiles(); System.out.println(Arrays.toString(files)); //列出系统的盘符 File[] roots = File.listRoots(); System.out.println(Arrays.toString(roots)); } }
遍历目录(了解)
看FileDemo3
/** * */ package com.qfedu.Day19.File; import java.io.File; public class FileDemo3 { public static void main(String[] args) { //需求listFiles() 打印出你workspace目下所有的文件包括文件夹下的文件(递归) //1.创建File对象 //ps:因个人电脑差异,建议不要遍历C盘 // File file = new File("D:\\DBworkspace"); // listFiles(file); //深度遍历目录树形式 File file1 = new File("C:\\"); showlistFilesTree(file1, 0); } /* * 简单遍历像是 */ public static void listFiles(File f) { //先打印第一次的file对象 System.out.println(f); File[] files = f.listFiles(); for(File file : files) { //只要判断是文件目录就继续遍历 if(file.isDirectory()) { listFiles(file); } } } /** * 遍历层级目录树形式 * @param f 遍历的目录 * @param level 是层级 * */ public static void showlistFilesTree(File f,int level) { StringBuilder sbr = new StringBuilder("| --"); for(int i = 0;i<level;i++) { sbr.insert(0, "| "); } //先进行判断 File[] files = f.listFiles(); if(files == null) { return; } for(File file:files) { //打印 concat 是拼接 --> + System.out.println(sbr.toString().concat(file.getName())); if(file.isDirectory()) { showlistFilesTree(file, level+1); } } } }
文件过滤器
看FileDemo4
/** * */ package com.qfedu.Day19.File; import java.io.File; import java.io.FilenameFilter; public class FileDemo4 { public static void main(String[] args) { File file = new File("D:\\Java\\week3\\Day13\\视频"); //实现此接口的类实例可用于过滤器文件名FilenameFilte //返回值是一个数组--->File对象的数组 File[] files = file.listFiles(new FilenameFilter() { /* *dir file对象 *name 是file路径下的而文件名字 */ @Override public boolean accept(File dir, String name) { return name.endsWith(".mp4") && new File(dir,name).isFile(); } }); for(File f : files) { System.out.println(f); } } }
IO流
ps:流不难,方法不多一共也就6个方法,写流的读写方式是固定形式,所以记下来!
IO --->Input/Output 输入输出的一种方式
为什么程序需要使用IO这种形式?
1.DVD系统中存储的数据是默认,还可以添加新数据,但是一旦程序关闭,所有的数据都无法保存下来
将数据保存到物理介质之中,就可以进行长久的保存
所有的数据都是存储到内存中,内存有一个最大的弊端[掉电易失],为了保证数据的安全性,此时需要一种方式
将当前内存中的数据保存到物理介质,就可以使用IO流的形式
ps:内存的读取速度绝对是大于磁盘的读取数据的
名词:
物理介质:文件,磁盘,网络,压缩包,等等
IO --> Input输入/output输出设备
学些的IO就是一个管道,有了这个管道之后就可以将内存中数据写的到磁盘中
有了这个管道之后就可以将磁盘中的文件写(读)会到内存中
IO流的分类:
流向划分:输入流 输出流
数据单位划分: 字节流(byte) 字符流(char)
功能划分: 转换流,节点流 ,包装流 ,缓冲流 等等
四大父类流
InputStream OutputStream 字节输入输出流
Reader Writer 字符输入输出流
InputStream和OutputStream
流向问题:
InputStream字节输入流 --> 读 从磁盘读取到内存中
OutputStream字节输出流 --> 写 从内存写入到磁盘
流中的数据类型: byte字节类型
InputStream字节输入流
当前流式父类流并且是一个抽象类所以不能直接创建对象
将内存中的文件写入到磁盘,然就将磁盘中的文件在读取到内存中
所以FileInputStream文件字节输入流
常用方法
FileInputStream(File file) 通过File对象创建文件字节输入流
FileInputStream(String name) 通过路径创建文件字节输入流对象
void close() 关闭流资源 需要在finally中使用
int read() 读取一个字节
int read(byte[] b) 读取字节数组长度的内容并存到字节数组中
int read(byte[] b, int off, int len) 读取字节数长度的内容,从字节数组中那个位置开始存储,读取的长度是多少
看FileInputStream包
/** * */ package com.qfedu.Day19.FileInputStream; //IO包下的流,所以若一个流对象就需要导入一个包,那么就需要很多的包 //所以,就以java.io.* 一次性导入所有IO包下类 import java.io.*; import java.util.Arrays; public class FileInputStreamDemo { public static void main(String[] args) { //先创建字节输入流对象 //ps .是当前路径 // FileNotFoundException 没有找到文件异常 抛出当前异常,路径错了 //在没有讲到对象流之前,所有的流都使用try...catch抓取 InputStream is = null; try { is = new FileInputStream("dir/file.txt"); /* * int read() 从此输入流中读取一个数据字节。 * int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 * int read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 */ //1.在文件中读取一个字节,文件中的内容 //ps:在控制台上打印的值是97 为什么? 因为是ASCII吗 //字节流 --> byte 将当前a转换为 ASCII来进行存储,所以就在控制台上看到97这个值 /* System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); System.out.println(is.read()); //若读取到文件末尾时,系统会返回一个负数表示读取到了文件的末尾 //那么这个负数就是-1 //假如,有某个判断只要判断读取到-1就到了文件的末尾,不读取了 // 如果没有读取到-1就可以继续读取 System.out.println(is.read()); */ //2.读取字节数组长度的内容,并存储到字节数组中 //创建一个字节数组 //ps:实际是先读取字节数组中长度的内容(数组的长度是多少就读取多少个字节) // 在存到当前字节数组中,所读取的内容就在字节数组存放 byte[] arr = new byte[10]; is.read(arr); System.out.println(Arrays.toString(arr)); //3.读取字节数组长度的内容,从什么位置开始读读取的长度是多少\ // byte[] arr = new byte[10]; // /* // * 第一个参数是字节数组 // * 第二个参数是从什么位置开始存储 // * 第三个参数是实际读取的长度是多少(存储的长度是多少) // */ // is.read(arr,2,5); // System.out.println(Arrays.toString(arr)); // //不要使用上面这个样的打印形式上面这种形式只能打印数值无法看到实际内容 // //将当前内容转换为字符串 // //第一个参数是字节数组 ,第二个参数是数组中存储元素的位置, 第三个参数是读取数组中内容的长度 // System.out.println(new String(arr, 2, 5)); //需要进行循环读数据应该如何使用 //当我们使用 read(byte[] b)方法进行数据读取或得到一个返回值 //是int类型,如果读取到文件末尾就返回-1,没有读取到文件末尾就返回实际读取的长度 //1.先创建字节数组并设置读取长度 byte[] buf = new byte[10]; //2.通过方法来进行读取 ,判断读取的实际长度是否到达-1,没有就继续读,有就停止读取 int len = 0; while( (len = is.read(buf)) != -1) { //2.在读取的过程中进行打印 System.out.println(new String(buf,0,len)); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //释放资源 //关闭流资源 if(is != null) { try { is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
OutputStream字节输出流
因为当前类是抽象类,所以不能直接创建对象
所以需要使用其子类FileOutputStream文件字节输出流
当前里流中有一个方法 flush
ps:在没有涉及到TCP网络的,写与不写flush这个方法的效果都是一样的
但实际有些细微的差别若调用flush,会加快流的流速
若是在TCP中必须调用次方法,不然流中的数据会被阻塞到网络中,所以这里必须添加flush
FileOutputStream(File file) 通过File对象创建文件字节输出流对象
FileOutputStream(File file, boolean append) 通过File对象创建文件字节输出流对象,并且进行内容追加
FileOutputStream(String name) 通过路径创建文件字节输出流对象
FileOutputStream(String name, boolean append) 通过File对象创建文件字节输出流对象,并且进行内容追加
ps:若想追加那么参数就传入 true
void close() 关闭流资源
void write(byte[] b) 将字节数组内容写入到文件
void write(byte[] b, int off, int len) 将字节数组内容写入到文件从什么位置开始写,写多长
void write(int b) 将一个字节的内容写入到文件
/** * */ package com.qfedu.Day19.FileOutputStream; import java.io.*; public class OutputStreamDemo { public static void main(String[] args) { OutputStream os = null; OutputStream oos = null; try { //创建文件字节输出流,就是向什么位置将文件写出去 //若写出的文件夹中没有用当前文件,会自动创建 //os = new FileOutputStream("dir/newFile.txt"); //创建文件字节输出流,就是向什么位置将文件写出去,确定追加 //不会覆盖原有文件内容,而是在原有文件内容的基础上继续写入 oos = new FileOutputStream("dir/newFile.txt",true); /* * void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 void write(byte[] b, int off, int len)将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 void write(int b) 将指定字节写入此文件输出流。 */ // os.write(97); // //getBytes()将当前字符串转换为字节数组 // os.write("abcdefg".getBytes()); // os.write("ABCD".getBytes(), 1, 3); oos.write("我是追加的内容".getBytes()); oos.flush(); System.out.println("老子写完了!!!!!"); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if(os != null) { try { oos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
总结:
FileInputSteam和FileOutputStream
字节流:数据是字节
必须会循环读取文件中的数据,需要在循环读取中将数据写出到文件中
/** * */ package com.qfedu.Day19.HomeWork; public class Poem { //诗词的名字 private String name; //作者 private String zuozhe; //朝代 private String chaodai; //内容 private String neirong; public Poem(String name, String zuozhe, String chaodai, String neirong) { super(); this.name = name; this.zuozhe = zuozhe; this.chaodai = chaodai; this.neirong = neirong; } public Poem() { super(); // TODO Auto-generated constructor stub } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getZuozhe() { return zuozhe; } public void setZuozhe(String zuozhe) { this.zuozhe = zuozhe; } public String getChaodai() { return chaodai; } public void setChaodai(String chaodai) { this.chaodai = chaodai; } public String getNeirong() { return neirong; } public void setNeirong(String neirong) { this.neirong = neirong; } @Override public String toString() { return "作者:"+zuozhe+"\n"+"朝代:"+chaodai+"\n"+"内容:"+neirong; } } /** * */ package com.qfedu.Day19.HomeWork; import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class Test { public static void main(String[] args) { Poem p1 = new Poem("春晓","孟浩然","唐朝","春天不洗脚,处处蚊子咬"); Poem p2 = new Poem("沁园春.雪","毛爷爷","近代","啊 全是雪............"); Map<String,Poem> map = new HashMap<>(); map.put(p1.getName(), p1); map.put(p2.getName(), p2); System.out.println("------------------ 国家图书馆诗词查阅系统 -------------------"); Scanner input = null; while(true) { System.out.println("请录入您要查看的诗词名:"); input = new Scanner(System.in); String name = input.next(); if(map.containsKey(name)) { System.out.println(map.get(name)); }else { System.out.println("诗词系统中没有当前诗词!!!!"); } System.out.println("还要继续阅读吗?请输入yes|no"); String res = input.next(); if("no".equals(res)) { System.out.println("谢谢使用!^-^"); break; } } } }