在java中流可类比为一个个数据的序列,所以在流中常用 byte[] 或 char[] 用作传输数据的小车,推荐使用 4096 (就是4k大小)作为传输一个流大小,当流的大小特别大时应使用 BufferedReader / BufferedWriter 做流的传输小车以提高效率,输入流表示从源读取数据(例如从硬盘文件读数据到内存中),输出流表示向一个目标写入数据(例如将内存中的数据写入到硬盘中)
IO流又可分为 字节流 和 字符流
IO流中的关系 - 图片来源菜鸟教程
字节流主要包括 FileInputStream 和 FileOutputStream
下面演示 FileInputStream
package java0713.ioDemo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * 演示字节流 * @author Administrator * */ public class FileInputStreamDemo { public static void main(String[] args) { File file = new File("e://2.txt"); // 连接文件源建立输入流 // 这条语句也可用InputStream is = new FileInputStream("FileAddress_StringPath")代替 try(InputStream is = new FileInputStream(file);) { byte[] buffer = new byte[4096]; int len = 0; StringBuilder sb = new StringBuilder(); // // 错误示范,慎重使用available // int size = is.available(); // for (int i = 0; i < size; i++) { // System.out.print((char)is.read()); // } do { // InputStream字节流公有方法read() // 读取buffer个单位字节数据,返回单个流可读取最大长度,返回下一字节数据,结尾返回-1,对buffer数组赋值 len = is.read(buffer); if(len>0) { // 为防止多出来的字节数组空间因未赋值而在转成字符串时变成空格,所以要限制它的长度为有效长度len,当len为-1时会报异常 sb.append(new String(buffer,0,len)); } else { break; } } while(true); // // 错误示范代码,条件写里面会报错 // do { // len = is.read(buffer); // sb.append(new String(buffer,0,len)); // } while(len>0); System.out.println(sb); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
在这里is流从源file指向buffer(buffer再流向至sb)
FileOutputStream 与 FileInputStream 用法类似,但是用数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了 close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之前先flush(),先清空数据。
package java0713.ioDemo; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * 演示输出流 * @author Administrator * */ public class FileOutputStreamDemo { public static void main(String[] args) { // 输出流连接目的地target try(OutputStream os = new FileOutputStream("e://3.txt");) { for (int i = 0; i < 255; i++) { os.write((char)i); os.write('/r'); os.write('/n'); } // flush方法,刷新缓冲区,强制写入 os.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println("FileOutputSteam writes file successfully!"); } }
其它流则有对象流(如输入输出集合框架对象)和二进制流(如输入输出基础数据类型)
字符流包括 InputStreamReader 和 OutputStreamWriter
字节流一次read返回一个字节,而字符流正如名字所示,一次read返回一个字符,所以字符流非常擅长输入输出有中文文本的流,而且用字符流输入输出对选择用何种方式的编码也非常方便
package java0713.ioDemo; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * 演示字符流Reader/Writer * @author Administrator * */ public class InputStreamReaderDemo { public static void main(String[] args) { try(InputStream fis = new FileInputStream("e://2.txt");) { InputStreamReader reader = new InputStreamReader(fis,"gbk"); StringBuilder sb = new StringBuilder(); while(reader.ready()) { // 字符流一次read()读取一个字符即两个字节 sb.append((char)reader.read()); } System.out.println(sb); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
OutputStreamWriter 方法与输入流类似,不再赘述