黑马程序员—Java基础—IO3
2015-11-04 20:32
567 查看
------- android培训、java培训、期待与您交流!
----------
IO3
一、字节流File读写操作
不需要flush刷新操作
二、IO应用—图片拷贝
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
字符流拷贝媒体文件,有可能不能使用
三、IO应用—拷贝MP3文件
演示mp3的复制。通过缓冲区。
BufferedOutputStream
BufferedInputStream
四、自定义字节流的缓冲区-read和write的特点
*知识扫盲:-1的二进制为1的二进制取反再加1
为什么复制的第一个字节为-1呢
11111111-111111110000000000101001001010100101010010101001010
byte: -1 ---> int : -1;
00000000 00000000 00000000 11111111 255
11111111 11111111 11111111 11111111
11111111 -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
00000000 00000000 00000000 11111111
0000-0001
1111-1110
000000001
1111-1111 -1
结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
五、读取键盘录入
读取键盘录入。
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
六、转换流
字符流:
FileReader
FileWriter。
BufferedReader
BufferedWriter
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。
能不能直接使用readLine方法来完成键盘录入的一行数据的读取。readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?
代码示例:
七、流操作规律1
1, 源:键盘录入。
目的:控制台。
2,需求:想把键盘录入的数据存储到一个文件中。
源:键盘。
目的:文件。
3,需求:想要将一个文件的数据打印在控制台上。
源:文件。
目的:控制台。
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
八、流操作规律2
FileWriter,GPK默认字符编码,OutputStreamWriter转换率可以接受指定字符集
需求:将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
**************
扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
但是FileWriter是使用的默认编码表。GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,
需要用到转换流。
九、改变标准输入输出设备
*知识补充:System提供的方法为静态,可以直接使用
----------
IO3
一、字节流File读写操作
不需要flush刷新操作
import java.io.*; class FileStream { public static void writeFile()throws IOException { FileOutputStream fos = new FileOutputStream("fos.txt"); //使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 fos.write("abcde".getBytes()); fos.close(); } public static void main(String[] args) throws IOException { //创建文件fos.txt readFile_2(); } public static void readFile_3()throws IOException { FileInputStream fis = new FileInputStream("fos.txt"); //int num = fis.available(); byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。 fis.read(buf); System.out.println(new String(buf)); fis.close(); } public static void readFile_2()throws IOException { FileInputStream fis = new FileInputStream("fos.txt"); byte[] buf = new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1)//len不等于-1,持续读下去 { fis.read(buf); //读到几个,打印几个数组 System.out.println(new String(buf,0,len)); } fis.close(); } public static void readFile_1()throws IOException { FileInputStream fis = new FileInputStream("fos.txt"); int ch = 0; while((ch=fis.read())!=-1) { System.out.println((char)ch); } fis.close(); } }
二、IO应用—图片拷贝
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
字符流拷贝媒体文件,有可能不能使用
import java.io.*; class CopyPic { public static void main(String[] args) { FileOutputStream fos = null; FileInputStream fis = null; try { fos = new FileOutputStream("c:\\2.bmp"); fis = new FileInputStream("c:\\1.bmp"); byte[] buf = new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } } catch (IOException e) { throw new RuntimeException("复制文件失败"); } finally { try { if(fis!=null) fis.close(); } catch (IOException e) { throw new RuntimeException("读取关闭失败"); } try { if(fos!=null) fos.close(); } catch (IOException e) { throw new RuntimeException("写入关闭失败"); } } } }
三、IO应用—拷贝MP3文件
演示mp3的复制。通过缓冲区。
BufferedOutputStream
BufferedInputStream
import java.io.*; class CopyMp3 { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); copy_2(); long end = System.currentTimeMillis(); System.out.println((end-start)+"毫秒"); } public static void copy_2()throws IOException { MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("c:\\9.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\3.mp3")); int by = 0; //System.out.println("第一个字节:"+bufis.myRead()); while((by=bufis.myRead())!=-1) { bufos.write(by); } bufos.close(); bufis.myClose(); } //通过字节流的缓冲区完成复制。 public static void copy_1()throws IOException { BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3")); int by = 0; while((by=bufis.read())!=-1) { bufos.write(by); } bufos.close(); bufis.close(); } }
四、自定义字节流的缓冲区-read和write的特点
*知识扫盲:-1的二进制为1的二进制取反再加1
import java.io.*; class MyBufferedInputStream { private InputStream in; private byte[] buf = new byte[1024*4]; private int pos = 0,count = 0; MyBufferedInputStream(InputStream in) { this.in = in; } //一次读一个字节,从缓冲区(字节数组)获取。 public int myRead()throws IOException { //通过in对象读取硬盘上数据,并存储buf中。 if(count==0) { count = in.read(buf); if(count<0) return -1; pos = 0; byte b = buf[pos]; count--; pos++; return b&255; } else if(count>0) { byte b = buf[pos]; count--; pos++; return b&0xff;//与上十六进制的255 } //为了编译通过,返回-1 return -1; } public void myClose()throws IOException { in.close(); } }
为什么复制的第一个字节为-1呢
11111111-111111110000000000101001001010100101010010101001010
byte: -1 ---> int : -1;
00000000 00000000 00000000 11111111 255
11111111 11111111 11111111 11111111
11111111 -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
00000000 00000000 00000000 11111111
0000-0001
1111-1110
000000001
1111-1111 -1
结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。
而在写入数据时,只写该int类型数据的最低8位。
五、读取键盘录入
读取键盘录入。
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
import java.io.*; class ReadIn { public static void main(String[] args) throws IOException { InputStream in = System.in; StringBuilder sb = new StringBuilder(); while(true) { int ch = in.read(); if(ch=='\r') continue; if(ch=='\n') { String s = sb.toString(); if("over".equals(s)) break; System.out.println(s.toUpperCase()); //删除缓冲区内容 sb.delete(0,sb.length()); } else sb.append((char)ch); } } }
六、转换流
字符流:
FileReader
FileWriter。
BufferedReader
BufferedWriter
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。
能不能直接使用readLine方法来完成键盘录入的一行数据的读取。readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢?
代码示例:
import java.io.*; class TransStreamDemo { public static void main(String[] args) throws IOException { //获取键盘录入对象。 //InputStream in = System.in; //将字节流对象转成字符流对象,使用转换流。InputStreamReader //InputStreamReader isr = new InputStreamReader(in); //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader //BufferedReader bufr = new BufferedReader(isr); //******键盘的最常见写法。 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); // OutputStream out = System.out; // OutputStreamWriter osw = new OutputStreamWriter(out); // BufferedWriter bufw = new BufferedWriter(osw); BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
七、流操作规律1
1, 源:键盘录入。
目的:控制台。
2,需求:想把键盘录入的数据存储到一个文件中。
源:键盘。
目的:文件。
3,需求:想要将一个文件的数据打印在控制台上。
源:文件。
目的:控制台。
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
八、流操作规律2
FileWriter,GPK默认字符编码,OutputStreamWriter转换率可以接受指定字符集
需求:将键盘录入的数据保存到一个文件中。
这个需求中有源和目的都存在。
那么分别分析
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
**************
扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
但是FileWriter是使用的默认编码表。GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,
需要用到转换流。
九、改变标准输入输出设备
*知识补充:System提供的方法为静态,可以直接使用
class TransStreamDemo2 { public static void main(String[] args) throws IOException { System.setIn(new FileInputStream("PersonDemo.java")); System.setOut(new PrintStream("zzz.txt")); //键盘的最常见写法。 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } }
相关文章推荐
- 不少程序员都会碰到的三个面试题
- Android面试题之——内存泄露
- 黑马程序员—Java基础—IO2
- 周一晚上(2015.11.4)朋友模拟的一次面试
- 面试题11:实现函数 double Power(double base, int exponent)。求base的exponent的次方。不使用库函数。
- 黑马程序员—Java基础—IO1
- 上周二的一个面试(==)
- 程序员如何写出一份好的文档?
- 黑马程序员——Java基础---面向对象
- 黑马程序员_简易版IE浏览器 2.0
- 对程序员最具影响力的十本书
- 黑马程序员-java基础(六)-集合
- 黑马程序员——java基础语法(三)---数组
- 每个程序员都该知道的10大编程格言
- 程序员遇到bug时常见的30种反应
- 一个半路出家的10年程序员:谈工作、学习与Qt
- 转:hive面试题
- 一个程序员的简洁职业生涯规划
- 嵌入式职业发展方向
- 黑马程序员-----Java概述