(1)I/O是Input和Output的缩写,I/O技术是非常使用的技术,用于处理数据传输,如读写文件,网络通讯等
(2)Java程序中,对于数据的输入/输出 *** 作以流(Stream)的方式进行
(3)java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并提供方法输入或输出数据
(1)按 *** 作数据单位不同分为:字节流(8bit),用来 *** 作二进制文件、字符流(以字符为单位),用来 *** 作文本文件
(2)按数据流的流向不同分为:输入流、输出流
(3)按流的角色不同分为:节点流、处理流(也叫包装流)
这四个基类都是abstract的,不能直接实例化,在使用时只能通过其子类来创建对象
流是文件传输的载体
2、InputStream 字节输入流InputStream 抽象类是所有类字节输入流的超类,其常用的子类有
(1)FileInputStream :文件输入流
(2)BufferedInputStream :缓冲字节输入流
(3)ObjectInputStream :对象字节输入流
package com.francis.inputstream; import org.junit.jupiter.api.Test; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class FileInputStream_ { //使用单个字符方式读取文件内容 @Test public void readFile01(){ String filePath = "f:\hello.txt"; int readData= 0; StringBuffer stringBuffer = new StringBuffer(); FileInputStream fileInputStream=null; try { fileInputStream = new FileInputStream(filePath); //read方法从输入流中读取一个字节的数据,如果没有输入可用,此方法将阻止, //read方法的返回值为char字符对应的ascII码,如果返回-1,表示读取完毕 while ((readData=fileInputStream.read())!=-1){ //将ascII转成字符 char chr = ((char) readData); stringBuffer.append(chr); System.out.println(chr); } System.out.println(stringBuffer); } catch (IOException e) { e.printStackTrace(); }finally { //输入流作为系统的资源,一定要记得关闭 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } //使用byte数组方式读取文件内容read(byte[] b) @Test public void readFile02(){ String filePath = "f:\hello.txt"; int readLen= 0; //一次性读取8个字节 byte[] buff= new byte[8]; StringBuffer stringBuffer = new StringBuffer(); FileInputStream fileInputStream=null; try { fileInputStream = new FileInputStream(filePath); //该方法一次性读取最多buff.length的数据,返回值为每次实际读取到的字节数,如果到达末尾,返回-1 while ((readLen=fileInputStream.read(buff))!=-1){ //这里需要注意,以后读取的时候有字符的话buff里的字符会依次被替换,如果没有字符,将保留上一次读取的字符 //所以不能用buff.length来构建String String str = new String(buff, 0, readLen); System.out.println(str); stringBuffer.append(str); } System.out.println(stringBuffer); } catch (IOException e) { e.printStackTrace(); }finally { //输入流作为系统的资源,一定要记得关闭 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }3、OutputStream 3.1、FileOutputStream 字节输出流
package com.francis.outputstream; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStream_ { @Test public void fileWrite(){ String filePath = "f:\write1.txt"; FileOutputStream fileOutputStream = null; try { fileOutputStream= new FileOutputStream(filePath); //写入一个字节 //fileOutputStream.write('F'); //写入字符串 String hello = "hello Beijing"; byte[] buff = hello.getBytes(); fileOutputStream.write(buff); } catch (IOException e) { e.printStackTrace(); }finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void fileWriteAppend(){ String filePath = "f:\write1.txt"; FileOutputStream fileOutputStream = null; try { fileOutputStream= new FileOutputStream(filePath,true); //写入一个字节 //fileOutputStream.write('F'); //写入字符串 String hello = "hello Beijing"; byte[] buff = hello.getBytes(); fileOutputStream.write(buff); } catch (IOException e) { e.printStackTrace(); }finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
输入流输出流配合案例:文件拷贝
package com.francis.outputstream; import org.junit.jupiter.api.Test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class FileCopy { @Test public void copyJpg(){ String srcFile="f:.jpg"; String destFile="f:.jpg"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; byte[] buff = new byte[1024]; int dataLen = 0; int times = 0; try { fileInputStream=new FileInputStream(srcFile); fileOutputStream = new FileOutputStream(destFile,true); while ((dataLen= fileInputStream.read(buff))!=-1){ times++; System.out.println(times); fileOutputStream.write(buff,0,dataLen); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileInputStream.close(); fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } finally { } } } }4、Reader 4.1、FileReader
相关方法
(1)构造器new FileReader(File/String)
(2)read,每次读取单个字符,返回该字符,如果到文件末尾,返回-1
(3)read(char[]) 批量读取多个字符数组,返回读取到的字符数,如果到达文件末尾,返回-1
相关API
(1)new String(char[]) 将char[]数组转成String
(2)new String (char[],off,len)将char[]的指定部分转成String
package com.francis.reader; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileReader_ { //每次读取一个字符 @Test public void readFile1() { String filePath = "f:\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 { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } //每次读取一个字符数组 @Test public void readFile2() { String filePath = "f:\story.txt"; FileReader fileReader = null; char[] buff = new char[8]; int dataLen =0; try { fileReader = new FileReader(filePath); System.out.println("使用char数组读取"); while((dataLen=fileReader.read(buff))!=-1){ System.out.print(new String(buff,0,dataLen)); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }5、Writer 5.1、FileWriter
相关方法
(1)new FileWriter(File/String),覆盖模式,相当于流的指针在首端
(2)new FileWriter(File/String,true)追加模式,相当于流的指针在末端
(3)write(),写入单个字符,
(4)write(char[] ) 写入指定字符数组
(5)write(char[],off,len)写入指定数组的指定部分
(6)write(String) 写入整个字符串
(7)write(String,off,len)写入字符串的指定部分
相关API
(1)String类:toCharArray(),将String转换成char[]
注意
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定文件
package com.francis.writer; import org.junit.jupiter.api.Test; import java.io.FileWriter; import java.io.IOException; public class FileWriter_ { @Test public void writeFile1() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); fileWriter.write('H'); fileWriter.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void writeFile2() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); char[] chars = "hello world2".toCharArray(); fileWriter.write(chars); fileWriter.flush(); System.out.println("写入成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void writeFile3() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); char[] chars = "hello world3".toCharArray(); fileWriter.write(chars, 0, 5); fileWriter.flush(); System.out.println("写入成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void writeFile4() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); String str = "hello world4"; fileWriter.write(str); fileWriter.flush(); System.out.println("写入成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void writeFile5() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath); String str = "hello world5"; fileWriter.write(str, 0, 5); fileWriter.flush(); System.out.println("写入成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void writeFile6() { String filePath = "f:\note.txt"; FileWriter fileWriter = null; try { fileWriter = new FileWriter(filePath, true); String str = "hello world6"; fileWriter.write(str); fileWriter.flush(); System.out.println("写入成功!"); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }6、节点流和处理流 6.1、基本介绍
(1)节点流可以从一个特定的数据源读取数据,如FileReader、FileWriter
(2)处理流也叫包装流,是“连接”已存在的流(节点流或处理流)纸上,为程序提供更为强大的读写功能,也更加灵活,如BufferReader、BufferWriter
(1)节点流是底层流/低级流,直接跟数据源相接
(2)处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
(3)处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要提现在以下两个方面
(1)性能的提高:主要以增加缓冲的方式来提高输入输出的效率
(2)便捷的 *** 作:处理流可能提供了便捷的方法来一次性输入输出大批量的数据,使用更加灵活便捷
BufferedReader 和 BufferedWriter属于字符处理流,是按照字符来读取数据的,关闭处理流时,只需要关闭外层流即可。这是因为在关闭处理流时,底层会调用节点流的close方法。
package com.francis.writer; import org.junit.jupiter.api.Test; import java.io.*; public class BufferedCopy { @Test public void copy(){ String srcFile = "f:\story.txt"; String destFile = "f:\story2.txt"; BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { bufferedReader = new BufferedReader(new FileReader(srcFile)); bufferedWriter= new BufferedWriter(new FileWriter(destFile,true)); String line ; while ((line=bufferedReader.readLine())!=null){ bufferedWriter.write(line); System.out.println(line); bufferedWriter.newline(); } //与fileWriter一样,需要flush或者close文件才会真正的被写入内容 bufferedWriter.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { bufferedReader.close(); //bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }6.4、处理流-BufferedInputStream 和 BufferedOutputStream
BufferedInputStream 是字节处理流,在创建BufferedInputStream 时,会创建一个内存缓冲区数组;BufferedOutputStream也是字节处理流,可以将多个字节写入到底层输出流中,而不必对每次字节写入调用底层系统。
package com.francis.outputstream; import org.junit.jupiter.api.Test; import java.io.*; public class BufferedCopy { @Test public void copy() { String srcFile = "f:.avi"; String destFile = "f:.avi"; BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile)); bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] buffer = new byte[1024]; int readLen= 0; while ((readLen =bufferedInputStream.read(buffer))!=-1){ bufferedOutputStream.write(buffer, 0, readLen); } System.out.println("拷贝成功"); } catch (IOException e) { e.printStackTrace(); } finally { try { if(bufferedInputStream!=null){ bufferedInputStream.close(); } if(bufferedOutputStream!=null){ bufferedOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }6.5、对象处理流-ObjectInputStream 和 ObjectOutputStream
当我们需要把一个数据及其类型保存到文件中,并且可以从文件中回复该数据及其类型,这时我们需要使用到对象流
序列化和反序列化
(1)序列化就是在保存数据时,不仅保存数据本身,还要保存数据的类型
(2)反序列化就是在恢复数据时,不仅要恢复数据的值,还要恢复数据的类型
(3)需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一
①Serializable,这是一个标记接口,没有方法需要实现
②Externalizable,该接口有一个方法需要实现,因此我们一般实现上面的Serializable接口
对象流介绍
功能:提供了对基本类型或对象类型的序列化和反序列化的方法
ObjectOutputStream 提供 序列化功能
package com.francis.outputstream; import org.junit.jupiter.api.Test; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; public class ObjectOutputStream_ { @Test public void writeObject() throws IOException { //这里的文件后缀名是随便写的,保存之后的文件并不是纯文本文件,而是有特殊的格式,就算写成txt也不是文本文件 //String filePath = "f:\object.txt"; String filePath = "f:\object.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); //基本数据类型会自动装箱,并且根据方法的名字,就可以推测,保存的类型是什么 oos.writeInt(100); oos.writeBoolean(true); oos.writeChar('a'); oos.writeDouble(2.1); oos.writeFloat(1.2f); oos.writeUTF("我爱你中国"); Dog dog1 = new Dog("黄色","小黄",1,"中国"); Dog dog2 = new Dog("黑色","小黑",2,"中国"); //如果对象没有实现序列化接口,会抛异常 oos.writeObject(dog1); oos.writeObject(dog2); oos.close(); } }
package com.francis.outputstream; import java.io.Serializable; public class Dog implements Serializable { //提高兼容性,当某天新增了一个属性,jvm不会认为是新的类,而是升级版 private static final long serialVersionUID = 1L; //这两个属性不会被序列化,可以在反序列化时输出验证 private static String nation ; private transient String color; private String name; private int age; public Dog(String color, String name, int age,String nation) { this.color = color; this.name = name; this.age = age; this.nation = nation; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } 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 "Dog{" + "color='" + color + ''' + ", name='" + name + ''' + ", age=" + age + ", nation=" + nation + '}'; } }
ObjectInputStream 提供 反序列化功能
package com.francis.inputstream; import com.francis.outputstream.Dog; import org.junit.jupiter.api.Test; import java.io.*; public class ObjectInputStream_ { @Test public void parseObject() throws IOException, ClassNotFoundException { String filePath = "f:\object.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //反序列化的顺序要跟序列化的顺序保持一致 System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readFloat()); System.out.println(ois.readUTF()); //读取对象时可能存在类型转换异常 Dog dog1 =(Dog) ois.readObject(); Dog dog2 =(Dog) ois.readObject(); System.out.println(dog2.getName()); //如果我们需要调用dog的方法,我们就需要向下转型,得保证在反序列化的 //环境下也存在Dog类,并且包名也要相同,特别是客户端和服务端的时候,并不在同一个系统下时 //要注意,这里我们就直接引用output包下的即可 System.out.println(dog1); System.out.println(dog2); ois.close(); } }
注意事项和细节说明
(1)在反序列化时,顺序要与序列化时保持一致
(2)要求反序列化和序列化的对象需要实现两个序列化接口的其中一个,一般我们实现Serializable
(3)序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性private static final long serialVersionUID = 1L;
(4)序列化对象时,默认将对象里的所有属性都进行序列化,但除了static或transient修饰的成员
(5)序列化对象时,要求里面属性的类型也需要实现序列化接口
(6)序列化具备可继承性,也就是某类已经实现了序列化,则它的所有子类也默认实现了序列化
System.in 标准输入流 默认设备时键盘
System.out 标准输出流 默认设备时显示器
package com.francis.standard; import org.junit.jupiter.api.Test; import java.util.Scanner; public class InputAndOutput { public static void main(String[] args) { //System.in的编译类型是public final static InputStream in = null; //System.ind的运行类型是BufferedInputStream,标准输入表示的就是键盘 System.out.println(System.in.getClass()); //System.out的编译类型是public final static PrintStream out = null; //System.out的运行类型PrintStream,标准输出表示的就是输出到键盘上 System.out.println(System.out.getClass()); //scanner每次回去处理流bufferedInputStream的缓冲区中去获取数据 Scanner scanner = new Scanner(System.in); System.out.println("请输入内容"); String next = scanner.next(); System.out.println(next); } }6.7、转换流处理流-InputStreamReader 和 OutputStreamWriter
乱码问题
package com.francis.transformation; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class CodeQuestion { public static void main(String[] args) throws IOException { //读取 f:\a.txt 文件到程序 //1. 创建字符输入流 BufferedReader [处理流] //2. 使用 BufferedReader 对象读取 a.txt //3. 默认情况下,读取文件是按照 utf-8 编码 String filePath = "f:\a.txt"; BufferedReader br = new BufferedReader(new FileReader(filePath)); String s = br.readLine(); //编码格式不统一,会出现中文乱码 System.out.println("读取到的内容: " + s); br.close(); //InputStreamReader //OutputStreamWriter } }
(1)InputStreamReader 是Reader的子类,可以将InputStream(字节流)转换成Reader(字符流)
(2)OutputStreamWriter是Writer的子类,可以将OutputStream(字节流)转换成Writer(字符流)
(3)当处理纯文本数据时,使用字符流效率更高,并且可以有效解决中文乱码问题,所以建议将字节流转换成字符流
(4)字符装换流可以在使用时指定编码格式(utf-8,gbk,gb2312,ISO8859-1)
package com.francis.transformation; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; public class InputStreamReader_ { public static void main(String[] args) throws IOException { String filePath = "f:\a.txt"; //1. 把 FileInputStream 转成 InputStreamReader //2. 指定编码 UTF-8 //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "UTF-8"); //3. 把 InputStreamReader 传入 BufferedReader //BufferedReader br = new BufferedReader(isr); //将 2 和 3 合在一起 BufferedReader br = new BufferedReader(new InputStreamReader( new FileInputStream(filePath), "UTF-8")); //4. 读取 String s = br.readLine(); System.out.println(s); //5. 关闭外层流 br.close(); } }6.8、打印处理流-PrintStream 和 PrintWriter
package com.francis.printstream; import java.io.PrintStream; public class PrintStream_ { public static void main(String[] args) throws Exception { PrintStream out = System.out; //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器 out.print("hello,world"); //因为 print 底层使用的是 write , 所以我们可以直接调用 write 进行打印/输出 out.write("同一个世界,同一个梦想".getBytes()); out.close(); //我们可以去修改打印流输出的位置/设备 //1. 输出修改成到 "f:\f1.txt" //2. "hello, 韩顺平教育~" 就会输出到f:f1.txt //3. public static void setOut(PrintStream out) { // checkIO(); // setOut0(out); // native 方法,修改了 out // } System.setOut(new PrintStream("f:\f1.txt")); System.out.println("北京欢迎你"); } }
package com.francis.printstream; import java.io.FileWriter; import java.io.PrintWriter; public class PrintWriter_ { public static void main(String[] args) throws Exception{ //PrintWriter printWriter = new PrintWriter(System.out); PrintWriter printWriter = new PrintWriter(new FileWriter("f:\f2.txt")); printWriter.print("hi, 北京你好~~~~"); printWriter.close();//flush + 关闭流, 才会将数据写入到文件.. } }7、Properties 类 7.1、基本介绍
(1)专门用于读取配置文件的集合类
配置文件的格式:
键=值
(2)注意,键值对不需要有空格,值不需要使用引号默认类型是String
(3)Properties的常见方法
①load加载配置文件的键值对到Properties对象
②将数据显示到指定设备
③getPRoperty(key)根据键获取值
④store将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果还有中文,保存的是unicode码
package com.francis.properties; import java.io.FileReader; import java.io.IOException; import java.util.Properties; public class Properties02 { public static void main(String[] args) throws IOException { //使用 Properties 类来读取 mysql.properties 文件 String filePath = "F:\DevWorkspace\code\exercises\JavaSE" + "\chapter19\src\mysql.properties"; //1. 创建 Properties 对象 Properties properties = new Properties(); //2. 加载指定配置文件 properties.load(new FileReader(filePath)); //3. 把 k-v 显示控制台 properties.list(System.out); //4. 根据 key 获取对应的值 String user = properties.getProperty("username"); String pwd = properties.getProperty("password"); System.out.println("用户名=" + user); System.out.println("密码是=" + pwd); } }
package com.francis.properties; import java.io.FileOutputStream; import java.io.IOException; import java.util.Properties; public class Properties03 { public static void main(String[] args) throws IOException { //使用 Properties 类来创建 配置文件, 修改配置文件内容 Properties properties = new Properties(); //创建 //1.如果该文件没有 key 就是创建 //2.如果该文件有 key ,就是修改 properties.setProperty("charset", "utf8"); properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode 码值 properties.setProperty("pwd", "888888"); //将 k-v 存储文件中即可 properties.store(new FileOutputStream("F:\DevWorkspace\code\exercises\JavaSE" + "\chapter19\src\mysql.properties"), null); System.out.println("保存配置文件成功~"); } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)