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操作应该处理IOException 14 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、读到结尾处,返回-1 15 * 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位开始存储,如果最后一次读取的字符<数组长度, 40 * !!!则只会覆盖前面的位置,之后的还是上一次读取的字符 41 * 数组长度最好是1024的整数倍 42 */ 43 FileReader fr = null; 44 char[] buff=new char[1024]; 45 int len=0; 46 try { 47 fr = new FileReader("demo.txt"); 48 while ((len=fr.read(buff)) != -1) { 49 System.out.println(new String(buff,0,len)); 50 } 51 } catch (IOException e) { 52 System.out.println(e.toString()); 53 }finally{ 54 if(fr!=null){ 55 try { 56 fr.close(); 57 } catch (Exception e2) { 58 throw new RuntimeException("关闭失败"); 59 } 60 } 61 } 62 } 63 }
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不是-1 30 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.java 42 */ 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、字节流--》字符流:解码,使用InputStreamReader 12 * 2、字符流--》字节流:编码,使用OutputStreamWriter 13 */ 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对象