IO流三:字节流文件读写操作、拷贝图片、带缓冲区的字节流、read()原理、读取键盘录入
2014-03-22 11:42
489 查看
1 字节流文件读写操作
字符流:FileReader、BufferedReaderFileWriter、BufferedWriter
字节流:InputStream :读
OutputStream :写
字符流操作字符数据,多用于文本文件。字节流操作字节数据,例如图片文件等。
字符流读入字符数组char[],字节流读入字节数组byte[]。
代码示例:
import java.io.*; class FileStreamDemo { public static void main(String[] args) throws IOException{ writeFile(); readFile_1(); readFile_2(); readFile_3(); } public static void writeFile() throws IOException{ FileOutputStream fos = new FileOutputStream("fos.txt");//文件不存在则创建。 //String类的getBytes()方法获取字节数组。 fos.write("FileStream".getBytes()); /* 字节流的写入不需要刷新。字符流需要刷新是因为,先逐个字节的将数据从流对象写入到一个缓冲区, 再查表,有匹配的字符时,再刷新写入目的地。 */ fos.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(); } 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){ //读取到buf数组中 System.out.println(new String(buf,0,len)); } fis.close(); } public static void readFile_3() throws IOException { FileInputStream fis = new FileInputStream("fos.txt"); //int num = fis.available(); //available方法获取流对象中的字节数,回车符'\r'和换行符'\n'各占一个。 byte[] buf = new byte[fis.available()]; //定义一个刚刚好的缓冲区,不用再循环了。 //但是如果这个数组长度过长,内存就溢出了。 fis.read(buf); System.out.println(new String(buf)); fis.close(); } }
2 拷贝图片
复制一个图片文件,用到的流对象:FileInputStream、FileOutputStream。思路:
1,字节流读取对象InputStream和图片文件相关联。
2,用字节流输出对象OutputStream创建一个文件,用于存储读取到底的图片数据。
3,通过循环读写,完成数据的存储。
代码示例:
import java.io.*; class CopyPictureDemo{ public static void main(String[] args){ FileInputStream fis = null; FileOutputStream fos = null; try{ fis = new FileInputStream("e:\\EVE.jpg"); //读 fos = new FileOutputStream("e:\\EVE_副本.jpg"); //写 byte[] buf = new byte[1024]; int len = 0; while((len=fis.read(buf))!=-1){ //读取到数组中 fos.write(buf,0,len); } } catch(IOException e){ System.out.println(e.toString()); } finally{ try{ if(fis!=null) fis.close(); } catch(IOException e){ System.out.println(e.toString()); } try{ if(fos!=null) fos.close(); } catch(IOException e){ System.out.println(e.toString()); } } } }
3 带缓冲区的字节流:复制MP3文件
通过复制MP3文件,演示带缓冲区的字节流:BufferedInputStream、BufferedOutputStream。代码示例:
import java.io.*; class CopyMp3Demo { public static void main(String[] args) throws IOException{ long start = System.currentTimeMillis(); //获取时间 copy_1(); long end = System.currentTimeMillis(); //获取时间 System.out.println((end-start)+"毫秒"); //执行时间 } //通过字节流的缓冲区完成复制 public static void copy_1() throws IOException{ BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("e:\\GetUp.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("e:\\GetUp-副本.mp3")); byte[] bt = new byte[1024]; int len = 0; while((len=bufis.read(bt))!=-1){ bufos.write(bt,0,len); } bufis.close(); bufos.close(); } //MyBufferedInputStream 的演示。 public static void copy_2() throws IOException{ MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("e:\\GetUp.mp3")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("e:\\GetUp-副本.mp3")); int by = 0; while((by=bufis.myRead())!=-1){ bufos.write(by); } bufis.myClose(); bufos.close(); } }
4 自定义带缓冲区的字节流和read()方法的原理
上一节代码CopyMp3Demo中copy_2的演示。代码示例:
import java.io.*; class MyBufferedInputStream { private InputStream in = null; private byte[] buf = new byte[1024]; //pos指针从数组中取元素,count计数器存储数组中的元素个数。 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; //从byte类型提升到int类型 } else if(count>0){ byte b = buf[pos]; count--; pos++; return b&255; //从byte类型提升到int类型 } return -1; } public void myClose() throws IOException{ in.close(); } }
-1的二进制表示:补码表示
0000 0001
1111 1110
1111 1111 -1 读到8个1,就返回了-1,所以没有执行read方法。
为什么read()返回是int类型,而不是byte类型?
因为返回byte类型的话,遇到连续8个1时,返回-1,误以为是结束标记,就不执行whlie循环。
提升到int类型后,32个1才表示“-1”,才是结束标记。
byte: -1 ----> int: -1 //一个int类型是32个二进制位,而一个字节8个二进制位,所以被提升了。
11111111 11111111 11111111 11111111 -1 //提升时若要还是-1,应在前面补1。
---> 00000000 00000000 00000000 11111111 255 //但为了避免遇到8个1返回-1,被误以为是结束标记。
//应该在前面补0。
11111111 --->提升了一个int类型,那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,既可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?
11111111 11111111 11111111 11111111
& 00000000 00000000 00000000 11111111 255 //和255做与运算,补0.
--------------------------------------------
00000000 00000000 00000000 11111111
事实上,read方法返回int类型时,进行补0的操作,
而write方法先进行去0的操作,再把11111111写入目的地,最终写入的数据还是这一个字节11111111。
5 读取键盘录入
System.out:对应标准的输出设备,控制台。System.in:对应标准的输入设备,键盘。
需求:
1,通过键盘读取录入。
2,当录入一行数据后,就将该行数据进行打印。
3,如果录入“over”的话,那么停止录入。
其实就是带缓冲区的IO流中readLine()的原理。
代码示例:
import java.io.*; class ReadInDemo{ public static void main(String[] args) throws IOException{ InputStream in = System.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(s.equals("over")) break; System.out.println(s); sb.delete(0,sb.length()); //清空缓冲区。 } else sb.append((char)ch); } } }
相关文章推荐
- JAVA之旅(二十七)——字节流的缓冲区,拷贝mp3,自定义字节流缓冲区,读取键盘录入,转换流InputStreamReader,写入转换流,流操作的规律
- JAVA之旅(二十七)——字节流的缓冲区,拷贝mp3,自定义字节流缓冲区,读取键盘录入,转换流InputStreamReader,写入转换流,流操作的规律
- IO流-3.【字节流】【字节流缓冲区】【键盘录入】【转换流】【流操作作规律】【输入输出重定向】
- 黑马程序员——7.1.IO(其他对象API(System类、Runtime类、Math类、Date类)字节流与字符流、IO异常处理、缓冲区、键盘录入、转换流、异常日志、流的操作总结)
- Java基础-字节流File读写操作和拷贝图片
- 文件操作ofstream,open,close,ifstream,fin,依照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件
- 黑马程序员--Java基础学习之IO流之字节流、字符流、读取写入文件、Copy文件、键盘输入输出、流操作的基本规律
- 黑马程序员——Java基础——字节流文件操作、键盘录入、转换流、流操作规律、异常日志等
- Java基础——IO(拷贝文件+字节流-字符流缓冲区(装饰设计)-转换流-IO操作规律-异常日志-系统信息列表输出)
- java IO 字节流、字节流读写文件、字节流缓冲区、文件拷贝、装饰设计模式
- 黑马程序员_Java基础_IO流_字节流,字节流操作文件,缓冲区字节流,流的使用规律,异常记录原理
- 字节流--读取、录入、拷贝文件实例
- 【19】IO流2_读写缓冲区,装饰设计模式,图片拷贝,IO流操作规律及其他
- 文件操作ofstream,open,close,ifstream,fin,按照行来读取数据, fstream,iosin iosout,fio.seekg(),文件写入和文件读写,文件拷贝和文件
- java:带有缓冲区的读写拷贝BufferedInputStream,BufferedOutputStream 读取写入文件
- 黑马程序员-字节流File读写操作_拷贝图片-mp3_自定义字节缓冲区
- java写文件读写操作(IO流,字节流)
- Matlab的各种数据读取、文件读写等操作汇总
- C语言文件读写操作中缓冲区问题和setbuf函数详解
- 【C语言】文件常用读写操作(含读取学生信息示例)