目录
IO流
文件
-
文件流:
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源到程序的路径
输出流:数据从程序到数据源的路径 -
常用的文件操作:
(1)创建文件public class FileCreate { //1.new File(String pathname)根据路径创建文件 @Test public void create1(){ String filePath = "d:\\news1.txt"; File file = new File(filePath); try { file.createNewFile(); } catch (Exception e) { e.printStackTrace(); } } //2.new File(File parent,String child)根据父目录文件+子路径创建 @Test public void create2(){ File parentFile = new File("d:\\"); String fileName = "news2.txt"; File file2 = new File(parentFile, fileName); try { file2.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } //3.new File(String parent,String child)根据父目录+子路径创建 @Test public void create3() { String parentName = "d:\\"; String childName = "news3.txt"; File file = new File(parentName, childName); try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } }
(2)其他操作
public class FileInformation { //获取文件信息 @Test public void info(){ //先创建文件对象 File file = new File("d:\\news1.txt"); //调用相应的方法 System.out.println("文件名字=" + file.getName()); System.out.println("绝对路径=" + file.getAbsolutePath()); System.out.println("父目录=" + file.getParent()); System.out.println("文件大小(字节)=" + file.length()); System.out.println("文件是否存在=" + file.exists()); System.out.println("是否是一个文件=" + file.isFile()); System.out.println("是否是是一个目录=" + file.isDirectory()); } }
(3)目录操作
public class Directory { //判断d:\\news1.txt是否存在,如果存在就删除 @Test public void m1(){ String filePath = "d:\\news1.txt"; File file = new File(filePath); if(file.exists()){ if(file.delete()){ System.out.println("删除成功"); }else { System.out.println("删除失败"); } }else { System.out.println("文件不存在"); } } //判断D:\\demo02 即目录是否存在,如果存在就删除 @Test public void m2(){ String directoryPath = "D:\\demo02"; File dir = new File(directoryPath); if(dir.exists()){ if(dir.delete()){ System.out.println("删除成功"); }else { System.out.println("删除失败"); } }else { System.out.println("目录不存在"); } } //判断D:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已存在,否则就创建 @Test public void m3(){ String directoryPath = "D:\\demo\\a\\b\\c"; File dic = new File(directoryPath); if(dic.exists()){ System.out.println("该目录存在"); }else { if(dic.mkdirs()){ System.out.println("创建成功"); }else { System.out.println("创建失败"); } } } }
IO流基本介绍
-
Java IO流:
(1)I/O 是 Input/Output 的缩写,I/O技术用于处理数据传输,如读写文件,网络通讯等
(2)Java程序中,对于数据的输入/输出操作以“流”的方式进行
(3)java.io 包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
(4)输入input:读取外部数据到程序中
(5)输出output:将程序数据输出到磁盘、光盘等存储数据 -
流的分类:
按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件
按数据流的流向不同分为:输入流、输出流
按流的角色的不同分为:节点流,处理流/包装流(抽象基类)) 字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer 注:Java的 IO 流共涉及40多个类,都是从如上4个抽象基类派生的;由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
字节流
-
字节流常用的子类:
FileInputStream:文件输入流
FileOutputStream:文件输出流
BufferedInputStream(是FilterInputStream的子类,FilterInputStream是InputStream的子类):缓冲字节输入流
ObjectInputStream:对象字节输入流 -
FileInputStream
/** * 演示FileInputStream的使用 * 字节输入流 文件 --> 程序 */ public class FileInputStream_ { /** * 演示读取文件 * 单个字节读取,效率低 */ @Test public void readFile01() { String filePath = "d:\\hello.txt"; FileInputStream fileInputStream = null; int readData = 0; try { //创建 FileInputStream 对象,用于读取文件 fileInputStream = new FileInputStream(filePath); //返回-1,表示读取完毕 while ((readData = fileInputStream.read()) != -1) { System.out.print((char) readData); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 使用read(byte[] b)读取,提高效率 */ @Test public void readFile02() { String filePath = "d:\\hello.txt"; FileInputStream fileInputStream = null; //定义一个字节数组 byte[] buf = new byte[8];//一次读8个 int readLen = 0; try { //创建 FileInputStream 对象,用于读取文件 fileInputStream = new FileInputStream(filePath); while ((readLen = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen)); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
FileOututStream
public class FileOutputStream_ { /** * 将数据写到文件中 * 如果文件不存在,则创建该文件 */ @Test public void writeFile() { String filePath = "d:\\a.txt"; FileOutputStream fileOutputStream = null; try { //使用这种方式,写入会覆盖原来的内容 fileOutputStream = new FileOutputStream(filePath); //fileOutputStream = new FileOutputStream(filePath,true);//是追加写入的方式 //写入一个字节 //fileOutputStream.write('H'); //写入一个字符串 String str = "hello,world"; //fileOutputStream.write(str.getBytes());//把字符串转成字节数组 fileOutputStream.write(str.getBytes(), 0, 3);//截取写入 } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
文件拷贝
public class FileCopy { public static void main(String[] args) { String srcFilePath = "d:\\hello.txt"; String destFilePath = "d:\\a.txt"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcFilePath); fileOutputStream = new FileOutputStream(destFilePath); byte[] buf = new byte[1024]; int readLen = 0; while ((readLen = fileInputStream.read(buf)) != -1){ fileOutputStream.write(buf,0,readLen);//一定要用这个方法 } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileInputStream != null){ fileInputStream.close(); } if (fileOutputStream != null){ fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
字符流
-
FileReadear
public class FileReader_ { /** * 单个字符读取 */ @Test public void readFile1(){ String filePath = "d:\\story.txt"; FileReader fileReader = null; int data = 0; try { fileReader = new FileReader(filePath); //循环读取 while ((data = fileReader.read()) != -1){ System.out.print((char)data); } } catch (IOException e) { e.printStackTrace(); } finally { if(fileReader != null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 字符数组读取 */ @Test public void readFile2(){ String filePath = "d:\\story.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[8]; try { fileReader = new FileReader(filePath); //循环读取 while ((readLen = fileReader.read(buf)) != -1){ System.out.print(new String(buf,0,readLen)); } } catch (IOException e) { e.printStackTrace(); } finally { if(fileReader != null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
-
FileWriter
public class FileWriter_ { @Test public void writeFile() { String filePath = "d:\\note.txt"; FileWriter fileWriter = null; char[] c = {'a', 'b', 'c'}; try { fileWriter = new FileWriter(filePath);//覆盖模式,后面加true 追加模式 //写入单个字符 fileWriter.write('H'); //写入指定数组 fileWriter.write(c); //写入指定数组的指定部分 fileWriter.write("LebronJames".toCharArray(), 0, 3); //写入整个字符串 fileWriter.write("Hello,world"); //写入字符串指定部分 fileWriter.write("hello", 0, 3); } catch (IOException e) { e.printStackTrace(); } finally { //对于FileWriter,一定要关闭流,或者flush,才能将数据真正写入到文件 try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件
节点流和处理流
-
节点流和处理流:
(1)节点流:节点流可以从一个特定的数据源读写数据,如 FileReader、FileWriter
(2)处理流:是连接在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如 BufferedReader、BufferedWriter -
节点流和处理流的区别和联系:
(1)节点流是底层流/低级流,直接跟数据源相连
(2)处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
(3)处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连 -
处理流的功能主要体现在以下两个方面:
(1)性能的提高:主要以增加缓冲的方式来提高输入输出的效率
(2)操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便 -
BufferedReader、BufferedWriter均属于字符流,不要去操作二进制文件,可能造成文件损坏,关闭时,只需关闭外层流即可
-
BufferedReader
public class BufferedReader_ { public static void main(String[] args) throws Exception { String filePath = "d:\\a.java"; BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); //读取 String line;//按行读取 while ((line = bufferedReader.readLine()) != null){ System.out.println(line); } //关闭流,只需关闭BufferedReader,因为底层会自动关闭节点流 bufferedReader.close(); } }
-
BufferedWriter
public class BufferedWriter_ { public static void main(String[] args) throws IOException { String filePath = "d:\\b.txt"; BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath)); //BufferedWriter不能追加,如果要追加,在节点流FileWriter加true, //即new BufferedWriter(new FileWriter(filePath,true)); bufferedWriter.write("hello"); //在写入多个数据时建议插入一个换行 bufferedWriter.newLine();//插入换行 //关闭 bufferedWriter.close(); } }
-
Buffered拷贝
public class BufferedCopy_ { public static void main(String[] args) { String srcFilePath = "d:\\a.java"; String destFilePath = "d:\\a2.java"; BufferedReader br = null; BufferedWriter bw = null; String line; try { br = new BufferedReader(new FileReader(srcFilePath)); bw = new BufferedWriter(new FileWriter(destFilePath)); //读取写入 while ((line = br.readLine()) != null) { bw.write(line); bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } if (bw != null) { bw.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
-
BufferedInputStream、BufferedOutputStream是字节处理流,操作二进制文件,也可以操作文本文件
-
使用BufferedInputStream、BufferedOutputStream拷贝和InputStream、OutputStream方式一样
序列化和反序列化
-
序列化和反序列化:
(1)序列化就是在保存数据时,保存数据的值和数据类型
(2)反序列化就是在恢复数据时,恢复数据的值和数据类型
(3)需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现 Serializble (这是一个标记接口,没有方法,推荐使用)、Externalizable 两个接口之一 -
对象处理流 ObjectInputStream、ObjectOutputStream 提供了对基本类型或对象类型的序列化和反序列化的方法,ObjectInputStream 提供反序列化功能,ObjectOutputStream 提供序列化功能
-
ObjectOutputStream
public class ObjectOutputStream_ { public static void main(String[] args) throws Exception { String filePath = "d:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); //序列化数据到文件 oos.write(100);//int -> Integer(实现了Serializable) oos.writeBoolean(true);//boolean -> Boolean(实现了Serializable) oos.writeChar('t');//char -> Character(实现了Serializable) oos.writeUTF("tom");//String(实现了Serializable) oos.writeObject(new Dog("jack" ,10)); oos.close(); } } class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } }
-
ObjectInputStream
public class OutInputStream_ { public static void main(String[] args) throws Exception { String filePath = "d:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //读取 //读取反序列化的顺序需要和保存数据(序列化)的顺序一致,否则会抛异常 ois.readInt(); ois.readBoolean(); ois.readChar(); ois.readUTF(); Object o = ois.readObject(); System.out.println(o.getClass()); //如果希望调用Dog方法,需要进行向下转型,需要将Dog类的定义拷贝到可以引用的位置 //此例在同一包内,不需引用 Dog dog = (Dog)o; dog.getName(); //关闭流 ois.close(); } }
-
对象处理流注意事项:
(1)读写顺序要一致
(2)要求实现序列化和反序列化对象,需要实现 Serializable
(3)序列化的类中建议添加 SerialVersionUID(序列化版本号,private static final long serialVersionUID = 1L),为了提高版本的兼容性
(4)序列化对象时,默认将里面所有属性都进行序列化,但除了 static 或 transient 修饰的成员
(5)序列化对象时,要求里面属性的类型也需要实现序列化接口
(6)序列化具备可继承性,即如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
标准输入流输出流
-
标准输入输出流
\ 类型 默认设备 System.in 标准输入 InputStream 键盘 System.out 标准输出 PrintStream 显示器 -
System.in 编译类型是 InputStream,运行类型是 BufferedInputStream
-
System.out 编译类型和运行类型都是 PrintStream
转换流
-
转换流 InputStreamReader 和 OutputStreamWriter,将字节流转换为字符流
-
InputStreamReade、和OutputStreamWriter基本介绍:
(1)InputStreamReader:Reader的子类,可以将 InputStream (字节流)包装成 Reader(字符流)
(2)OutputStreamWriter:Writer的子类,实现将 OutputStream (字节流)包装成 Writer(字符流)
(3)当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所有建议将字节流转换成字符流
(4)可以在使用时指定编码格式,入UTF-8,GBK等 -
InputStreamReader
public class InputStreamReader_ { public static void main(String[] args) throws Exception { String filePath = "d:\\a.txt"; InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk"); BufferedReader br = new BufferedReader(isr);//读取 String s = br.readLine(); System.out.println(s); br.close(); }
-
OutputStreamReader
public class OutputStreamWriter_ { public static void main(String[] args) throws Exception { String filePath = "d:\\b.txt"; OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath),"gbk"); osw.write("hi"); osw.close(); } }
打印流
-
打印流(只有输出流,没有输入流)分为 PrintStream 和 PrintWriter
-
PrintStream
public class PrintStream_ { public static void main(String[] args) throws IOException { PrintStream out = System.out; out.print("hello"); //print底层调用的是write方法,所以也可以用write方法 out.write("hello".getBytes()); out.close(); //可以修改打印输出的位置 System.setOut(new PrintStream("d:\\c.txt"));//修改成打印到这个文件 } }
-
PrintWriter
public class PrintWriter_ { public static void main(String[] args) throws IOException { PrintWriter printWriter = new PrintWriter(System.out); printWriter.print("hello"); printWriter.close(); PrintWriter printWriter1 = new PrintWriter(new FileWriter("d:\\d.txt")); printWriter1.print("hello~"); printWriter1.close(); } }
Properties
-
Properties类是专门用来读写配置文件的集合类,配置文件的格式:键=值(注:键值对不需要有空格,值不需要用引号引起来,默认类型是String)
-
Properties类常用方法
public class PropertiesMethod1 { public static void main(String[] args) throws IOException { //读取 src 目录下 xxx.properties文件 Properties properties = new Properties(); //1. 加载文件 load properties.load(new FileReader("src\\xxx.properties")); //2. 显示 k-v list方法 properties.list(System.out); //3. 根据key获取对应的值 String user = properties.getProperty("user"); System.out.println(user); } } public class PropertiesMethod2 { public static void main(String[] args) throws IOException { //使用Properties类创建或修改文件 Properties properties = new Properties(); //创建文件 //如果该文件没有key,就是创建 //如果该文件有key,就相当于是修改 properties.setProperty("charset","utf8"); properties.setProperty("user","tom"); properties.setProperty("pwd","abc111"); //4. 将k-v存储到文件中即可 store方法 null表示不设置注释 properties.store(new FileOutputStream("src\\mysql2.properties"),null); } }