IO流:就是input/output输入/输出流。
一、字节流操作文件的便捷类:FileWriter和FileReader
1 import java.io.FileWriter; 2 import java.io.IOException; 3 4 public class FileWriterDemo { 5 private static final String LINE_SEPARATOR=System.getProperty("line.separator"); 6 public static void main(String[] args) throws IOException{ 7 /*FileWriter类是Writer类的一个实现,用于向文件中写入字符 8 * io操作可能会触发IOException. 9 */10 demo();11 }12 13 //1、io操作应该处理IOException14 public static void demo() throws IOException {15 /*2、FileWriter类有多个构造函数,但是必须指定一个预期写入的目标文件,16 * 下面是字符串指定的文件,如果文件不存在则创建并写入内容;如果存在则先删除在创建并写入17 */18 FileWriter fw=new FileWriter("demo.txt");19 //3、write()是将内容写入到缓冲区中,而非硬盘中20 fw.write("asd"+LINE_SEPARATOR+"fgh"+LINE_SEPARATOR);21 //4、flush()是将缓冲区内容刷新到硬盘中22 fw.flush();23 //5、close()是两步操作:先刷新,在关闭24 fw.close();25 //如果想要在其后追加内容而非覆盖,则可以使用第二个boolean参数的构造方法26 FileWriter fw2=new FileWriter("demo.txt",true);27 fw2.write("这是追加的内容,使用了第二个boolean参数,没有将前面内容覆盖");28 fw2.close();29 }30 }
1 import java.io.FileReader; 2 import java.io.IOException; 3 4 public class FileReaderDemo { 5 6 public static void main(String[] args){ 7 readDemo(); 8 readDemo2(); 9 }10 11 public static void readDemo(){12 /*FileReader类是读取文件内容的Reader类的实现,特点13 * 1、继承了read(),但是每次只能读取一个字符,!!!范围在 0 到 65535 之间 (0x00-0xffff)14 * 2、读到结尾处,返回-115 * 3、独处的数据是int类型而非char类型,可以进行强转16 */17 FileReader fr = null;18 try {19 fr = new FileReader("demo.txt");20 while (fr.read() != -1) {21 System.out.println((char)(fr.read()));22 }23 } catch (IOException e) {24 System.out.println(e.toString());25 }finally{26 if(fr!=null){27 try {28 fr.close();29 } catch (IOException e2) {30 throw new RuntimeException("关闭失败");31 }32 }33 }34 }35 36 public static void readDemo2() {37 /*第二种方式是先创建一个数组,然后将读取的字符存入其中,然后可以将字符数组转为字符串然后读取38 * 优点是一次可以读取多个,减少循环的次数39 * !!!注意:每次都会读取数组长度的字符,并从0位开始存储,如果最后一次读取的字符
1 import java.io.FileWriter; 2 import java.io.IOException; 3 4 public class IOExceptionDemo { 5 private static final String LINE_SEPARATOR=System.getProperty("line.separator"); 6 7 public static void main(String[] args){ 8 demo(); 9 }10 11 public static void demo() {12 /*流类异常的处理:指的是那些需要打开/关闭资源的类,如IO流和数据库操作,13 * 1、就算出现异常,也要关闭资源,所以需要使用finally语句将关闭操作包含14 * 2、由于{}是一个单独的作用域,而这个资源需要在try和finally中分别操作,15 * !!!所以需要将资源定义在try结构之前16 * 3、关闭操作在finally中也可能出错,所以也需要单独进行try操作17 * !!!4、在关闭资源之前应该先判断是否打开该资源,因为可能打开时就失败了18 */19 FileWriter fw =null;20 try {21 fw = new FileWriter("demo.txt");22 23 fw.write("asd" + LINE_SEPARATOR + "fgh" + LINE_SEPARATOR);24 } catch (IOException e) {25 System.out.println(e.toString());26 }finally{27 if(fw!=null){28 try {29 fw.close();30 } catch (Exception e2) {31 throw new RuntimeException("关闭失败");32 }33 }34 }35 }36 }
缓冲区BufferedWriter/BufferedReader是用来提高流操作的效率,将要读写的内如存放在内存中统一读取,减少IO操作次数
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileReader; 4 import java.io.FileWriter; 5 import java.io.IOException; 6 7 public class BufferDemo { 8 public static void main(String[] args) throws IOException{ 9 //BufferedWriterDemo();10 BufferedReaderDemo();11 }12 13 public static void BufferedWriterDemo() throws IOException {14 //缓冲区必须封装一个字符流对象,其实内部就是用数组将字符流读取的内容先保存之后统一输出15 FileWriter fw=new FileWriter("bufferdemo.txt");16 BufferedWriter bw=new BufferedWriter(fw);17 bw.write("asdsf");18 bw.newLine();19 bw.write("这是新一行,使用缓冲区对象的方法换行");20 //这里使用缓冲区对象的close()其实就是使用字符流对象的该方法21 bw.close();22 }23 24 public static void BufferedReaderDemo() throws IOException {25 FileReader fr=new FileReader("bufferdemo.txt");26 //缓冲区内部其实就是一个数组,在这里体现的更明显27 BufferedReader br=new BufferedReader(fr);28 String line="";29 //BufferedReader类有一个特殊方法:就是读取一行内容,!!!读到最后返回null不是-130 while((line=br.readLine())!=null){31 System.out.println(line);32 }33 br.close();34 }35 }
下图是缓冲区实现的原理图
缓冲区对象还有一个子类LineNumberReader可以读取行号,原理类似
二、字节流操作文件的便捷类:FileOutputStream和FileInputStream,和字符流对象类似
1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 6 public class ByteStreamDemo { 7 8 public static void main(String[] args) { 9 /*字节流演示:直接操作底层2进制,不管编码。和字符流的区别是10 * 1、使用的是字节数组,每次读取1个字节,如果字符超出1字节会被剪切11 * 2、不用刷新flush(),因为会直接输出,但是需要close()12 */13 FileOutputStreamDemo();14 FileInputStreamDemo();15 }16 17 public static void FileOutputStreamDemo() {18 FileOutputStream fos=null;19 try {20 fos = new FileOutputStream("ByteStream.txt");21 fos.write("abcdefg".getBytes());22 } catch (IOException e) {23 e.printStackTrace();24 }finally{25 if(fos!=null){26 try {27 fos.close();28 } catch (IOException e) {29 throw new RuntimeException("关闭失败");30 }31 }32 }33 }34 35 public static void FileInputStreamDemo() {36 FileInputStream fis=null;37 try {38 fis = new FileInputStream("Bytestream.txt");39 /*FileInputStream对象available()可以直接访问文件的字节长度,所以比较简便的读取40 * !!!注意:如果文件内容过程,例如一部电影,就不能使用这种方法,因为创建的数组过长41 * 但是该方法可以用在对文件的分段读取上42 */43 byte[] b=new byte[fis.available()];44 fis.read(b);45 System.out.println(new String(b));46 } catch (IOException e) {47 e.printStackTrace();48 }finally{49 try {50 51 fis.close();52 } catch (IOException e) {53 throw new RuntimeException("关闭失败");54 }55 }56 }57 58 }
字节流对象也有对应的缓冲区对象:BufferedOutputStream和BufferedInputStream
三、标准输入:即通过键盘录入数据
1 import java.io.IOException; 2 import java.io.InputStream; 3 4 public class ReadKey { 5 6 public static void main(String[] args) throws IOException { 7 readkeydemo(); 8 readkeytest(); 9 }10 11 public static void readkeydemo() throws IOException {12 //1、通过System.in获取标准输入流对象13 InputStream in=System.in;14 /*2、通过read()来读取标准输入设备的输入数据,特点:15 * 1、!!!注意在读取完之前/抛出异常之前总是阻塞16 * 2、内容输入完使用Enter回车键结束,即使输入多个字符,该方法一次只能读取一个17 * !!!注意:实际的输入内容包括回车符\r(13),换行符\n(10)18 */19 int context=in.read();20 System.out.println(context);21 context=in.read();22 System.out.println(context);23 context=in.read();24 System.out.println(context);25 context=in.read();26 System.out.println(context);27 //3、!!!标准的输入/出对象在关闭之后就不能再打开了,所以不要手动关闭,会在程序结束时自动关闭28 //in.close();29 }30 31 public static void readkeytest() throws IOException {32 /*读取用户输入信息,以over结束而不是以回车符结束33 * 1、既然不使用回车符结束就要将其避免,34 * 当读到\r时跳过,下一个若是\n,表示一行的结束35 * 2、在一行结束时应该先判断是否是over,如果是则跳出循环,36 */37 InputStream in=System.in;38 StringBuffer sb=new StringBuffer();39 int ch=0;40 /*下面循环中的操作就是多次读取一行信息,和字符流BufferedReader中的readLine()相似,41 * 只是需要将字节流转换为字符流才能操作,见InputStreamReaderDemo.java42 */43 while((ch=in.read())!=-1){44 if(ch=='\r'){45 continue;46 }47 if(ch=='\n'){48 String str=sb.toString();49 if(str.equals("over")){50 break;51 }52 System.out.println(str);53 sb.delete(0, sb.length());54 }else{55 sb.append((char)(ch));56 }57 }58 }59 }
四、字节流到字符流的转换InputStreamReader和OutputStreamWriter
1 import java.io.BufferedReader; 2 import java.io.BufferedWriter; 3 import java.io.FileWriter; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.io.InputStreamReader; 7 8 public class StreamtoReaderWriter { 9 public static void main(String[] args) throws IOException{10 /*字符流=字节流+编码,在Java中有对象可以实现字节流和字符流之间的转换11 * 1、字节流--》字符流:解码,使用InputStreamReader12 * 2、字符流--》字节流:编码,使用OutputStreamWriter13 */14 //readKeyTest();15 OutputStreamWriterDemo();16 }17 18 public static void readKeyTest() throws IOException {19 InputStream in=System.in;20 InputStreamReader isr=new InputStreamReader(in);21 BufferedReader br=new BufferedReader(isr);22 String str=null;23 while((str=br.readLine())!=null){24 if(str.equals("over")){25 break;26 }27 System.out.println(str);28 }29 }30 31 public static void OutputStreamWriterDemo() throws IOException {32 /*这个函数是将System.out用流的方式实现了,其实其本身就是一种流33 * 并且可以将一个输入流内容输出到指定位置,扩展了System.out只能输出到控制台的功能34 */35 BufferedReader br=new BufferedReader(new InputStreamReader(System.in));36 BufferedWriter bw=new BufferedWriter(new FileWriter("a.txt"));37 String str=null;38 while((str=br.readLine())!=null){39 if(str.equals("over")){40 bw.close();41 break;42 }43 //System.out.println(str);44 bw.write(str);45 bw.newLine();46 bw.flush();47 }48 }49 }
!!!注意:System.out对象就是PrintStream的一个实例,用于方便的输出各种类型的数据;而System.in就是InputStream的一个实例
!!!PrintStream对象的println()会在写入byte[]之后自动添加换行符(意味着结束此行),并自动刷新,例如out对象的println()
五、流对象该如何选择
文件系统操作:IO流操作是对数据的操作,但是不能操作文件本身,Java中将对文件/文件夹的操作封装为File对象