InputStream 抽象字节输入流类
OuputStream 抽象字节输出流类
Reader 抽象字符输入流类
Writer 抽象字符输出流类
1.抽象字符流: Reader Writer
2.文件字符流: FileReader FileWriter
3.缓冲字符流: BufferedReader BufferedWriter
/**
*凡是字符流都有缓存,写数据时一定要记得刷缓存(flush),
否则数据不一定会及时写出去。close方法在关流之前会调一次flush
*/
1.需要套接,里面可套接一个文件输入,输出流
2.写的时候可利用溢出来控制循环结束
如:
- short i=0, j=1;
- do{
- out.writeInt(i);
- out.writeInt(j);
- i = (short) (i + j);
- j = (short) (i + j);
- }while(i>0);//利用溢出来控制循环结束,i>0开始循环,总会加到溢出的时候
3.读的时候可利用in.available判断循环结束,也可利用异常的方式判断文件结束
如: while(in.available()>0){//利用available()来判断文件结束
- while(true){//方式二利用异常来判断文件结束
- try {
- int n= din2.readInt();//读到文件末尾则抛出EOFException
- System.out.println(n);
- } catch (IOException e) {
- break;//读到文件末尾,跳出循环----读动作结束
- }
- }
1.创建一个文件流
如:
- String dir2 = "D:/mycode/ioDemo/b/";
- String fileName = "3.jpg";
- File dir = new File(dir2);//注意dir2是路径不是文件夹
- if(!dir.exists()){
- dir.mkdirs();
- }
- FielOutputStream out = new FileOutputStream(dir2+fileName);
2.可利用In.available判断循环结束
如:
- byte buf[] = new byte[512];
- while(in.available()>0){
- int len = in.read(buf);
- out.write(buf,0,len);
- }
3.文件输出流可以以追加的方式写文件,即程序运行几次就往目标文件写入几次信息
如:
- String str = "门前大桥下游过一群鸭,快来快来数一数,2.4.6.7.8";
- FileOutputStream out = new FileOutputStream("c.txt",true);
- out.write(str.getBytes("gbk"));
1.输出的类对象必须实现序列化(即实现Serializabe接口)
2.一般也需要套接一个文件字节输入,输出流
3.利用异常来结束文件的读取
如:
- while(true){//objecteInputstream用异常来结束文件的读取
-
- Person p = (Person) in.readObject();
-
- System.out.println(p);
-
- }
1)只有输出没有输入。PrintStream是字节打印流,PrintWriter是字符打印流。
2)能够方便地打印各种数据“值表示形式”,提供了一系列的打印功能(只有它有,其它流都没有。)
3)和其他输出流不同,它永远不会抛出IOException异常(构造方法除外),异常内部解决且设置了内部标志。
4)可创建具有自动刷新的功能,可使用带换行符的println()方法。
autoFlush - boolean 变量;如果为 true,则 println、printf 或 format 方法将刷新输出缓冲区。---其实是因为这几个方法中帮我们调用了out.flush()。
5)(在构造方法中)可以指定字符集编码的。
CharArrayReader与CharArrayWriter字符数组流
StringReader 与 StringWriter字符串流
1、用于操作字节数组的流对象,其实它们就是对应设备为内存的流对象。
2、该流的关闭是无效的,因为没有调用过系统资源。
3、按照流的读写思想操作数组中元素。
如:
// 使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
- ByteArrayInputStream baim = new ByteArrayInputStream("wozuishuai".getBytes());
- ByteArrayOutputStream baom = new ByteArrayOutputStream();
- int len = 0;
- while((len=baim.read())!=-1){
- baom.write(len);
- }
- System.out.println( baom.toString() );
在使用缓冲输入输出流的时候,推荐用法:
如:DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("a/g.txt")));
转换流功能1:充当字节流与字符流之间的桥梁
//InputStreamReader把字节流输入流转换为字符输入流,从键盘输入是流 //OutputStreamWriter把字符流转换为字节流,从纯文本读数据为字符流
如:
- InputStreamReader in = new InputStreamReader(System.in)
-
- BufferedWriter out =
-
- new BufferedWriter(
-
- new OutputStreamWriter(
-
- new FileOutputStream("a/h.txt")));
转换流功能2:字符编码转换
如:
- BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a/test3.txt"),"utf-8")); 写
-
- //BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("a/test_utf8.txt"),"utf-8") ); 读
- bw.write(str+"\n");//Linux方式。该方式用记事本不是换行显示,但写字板是
-
- //bw.write(str+"\r\n");//windows方式。该方式用记事本和写字板都是换行显示
-
- out.newLine();//根据系统平台,自动添加(回车)换行
- 对多个流进行合并
- FileInputStream f2 = new FileInputStream("seq/seq2.txt");
- FileInputStream f3 = new FileInputStream("seq/seq3.txt");
-
- ArrayList<FileInputStream> list= new ArrayList<FileInputStream>();
- list.add(f2);
- list.add(f3);
- //public static <T> ArrayList<T> list(Enumeration<T> e)
- //返回一个指定 collection 上的枚举。
- Enumeration<FileInputStream> en= Collections.enumeration(list);
- SequenceInputStream sis = new SequenceInputStream(en);//★
- //以上为从源读
- 如:/*以后我们开发后台会遇到一个乱码场景:
- * 1、浏览器编码并发送(str的字节数组--码值)--->
- * 2、浏览器接收并解码(查iso8859-1表,得到字符串name),
- * 传参给 MyServlet --->
- * 3、MyServlet接收到的name参数就是乱码
- */
-
- String str = "张三";
-
- //通过编译平台得到编码
-
- byte buf[] = str.getBytes("utf-8");
-
-
-
- //模拟浏览器的处理(解码--解错了,即浏览器解码所用的码表可能与你编码所用的码表不同)
-
- String str1 = new String(buf,"gbk");
-
- System.out.println(str1);//浏览器解码所得的信息为乱码
-
-
-
- //此时,若想得到原来的信息,既要将错误的浏览器解码所得出的乱码信息,用
-
- //浏览器的编码,从新解码,还原出正确的编码,再将正确的编码,用你自己原本
-
- //的编译平台上的码表,进行解码
-
-
-
- byte buf1[] = str1.getBytes("gbk");
-
-
-
- String str3 = new String (buf1,"utf-8");
-
- System.out.println(str3);
- private transient int num=30;//如果不想序列化某个非静态变量, 可以把它设成瞬时
- //如果没有transient则输出的num值为30,有则为0
- private int age;
- //只有对象中的非静态变量才会被序列化, 静态变量和方法都是不会被存入文件的。
- public static int count=0;//序列化时,静态变量是不会存在于对象图即静态变量是不会被存入的。
- public Person(String name,int age){
- this.name = name;
- this.age = age;
- count++;
- }
- 写: Person p = new Person("jack",18);
- 读:while(true){
- Person p = (Person) in.readObject();
- System.out.println(p);
- }
- 结果:jack, 18, count:0, num:0
流是用来处理数据的。
处理数据时,一定要先明确数据源与数据目的地(数据汇)。
数据源可以是文件、键盘或者其他流。
数据目的地可以是文件、显示器或者其他流。
流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。
1、明确源和目的。
源:InputStream Reader 一定是被读取的。
目的:OutputStream Writer 一定是被写入的。
2、处理的数据是否是纯文本的数据?
是:使用字符流。Reader Writer
否:使用字节流。 InputStream OutputStream
3、明确数据所在的设备:
源设备:
键盘(System.in)
硬盘(FileXXX)FileReader FileInputStream
内存(数组)ByteArrayInputStream CharArrayReader StringReader
网络(Socket)
目的设备:
显示器(控制台System.out)
硬盘(FileXXX)FileWriter FileOutputStream
内存(数组)ByteArrayOutputStream CharArrayWriter StringWriter
网络(Socket)
4、明确是否需要额外功能:
1) 是否需要高效?缓冲区Buffered (字符与字节各两个)。
2) 是否需要转换?转换流 InputStreamReader OutputStreamWriter
3) 是否操作基本数据类型? DataInputStream DataOutputStream
4) 是否操作对象(对象序列化)? ObjectInputStream ObjectOutputStream
5) 需要对多个源合并吗? SequenceInputStream
6) 需要保证数据的表现形式到目的地吗? PrintStream 或 PrintWriter
例子:
- 1.需求1:复制一个文本文件。
- a明确源和目的。
- 源:InputStream Reader
- 目的:OutputStream Writer
- b.处理的数据是否是纯文本的数据?
- 源:Reader
- 目的:Writer
- c.明确数据所在的设备。
- 源:file(硬盘)
- 目的:file(硬盘)
- FileReader fr = new FileReader("a.txt");
- FileWriter fw = new FileWriter("b.txt");
- d.明确是否需要额外功能?
- BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
- BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));