黑马程序员 java基础<四>--IO流(2)
来源:互联网 发布:淘宝实名认证怎么注销 编辑:程序博客网 时间:2024/06/16 00:11
-------android培训、java培训、java学习型技术博客、期待与您交流! ----------
知识点二 字节流
一、概述:
1、字节流的操作原理和字符流类是相似的,只不过字节流可以对图片、音频和视频媒体进行操作。
2、由于媒体数据中都是以字节存储的,所以,字节流对象可直接对媒体进行操作,可以不用再进行刷新流的动作。
3、读写字节流:InputStream ---> 输入流(读)
OutputStream ---> 输出流(写)
4、不用进行刷新流的动作的原因:
因为字节流操作的是字节,即数据的最小单位,不需要像字符流一样要进行转换为字节。可直接将字节写入到指定文件中,但是需要在写代码的时候,如果有字符串,要将字符串转为字节数组再进行操作。
5、字节流所特有方法:
int available() ---> 放回数据字节的长度,包含终止符
在定义字节数组长度的时候,可以用到这个方法:byte[] = new byte[fos.available()] (fos为字节流对象)
但是,对于这个方法要慎用,如果字节过大,比如一部电影(几个G),那么如此大的数组就会损坏内存,超过jvm所承受的大小(指定内存为64M)。
举例:
/*字符流:FileReader FileWriterBufferedReaderBufferedWriter字节流:两个基类:InputStream(读) OutputStream(写)需求:想要操作图片数据,这时候就要用到字节流*/import java.io.*;class FileStream{ public static void main(String []args) throws IOException { // writeFile(); // readFile_1(); // readFile_2(); readFile_3(); } 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) { 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();//这种方式要慎用,数据不是太大的话,可以这样使用byte[] buf=new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了 fis.read(buf); // System.out.println("num="+num); System.out.println(new String(buf)); fis.close(); } public static void writeFile() throws IOException { FileOutputStream fos=new FileOutputStream("fos.txt"); //将字符串变为字节数组 fos.write("abcde".getBytes()); fos.close(); }}
二、复制媒体文件(一张图片):
1、思路:
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("写入关闭失败");}}}}三、字节流缓冲区:
1、读写特点:
read():会将字节byte型值提升为int型值
write():会将int型强转为byte型,即保留二进制数的最后八位。
2、原理:将数据拷贝一部分,读取一部分,循环,直到数据全部读取完毕。
1)先从数据中抓取固定数组长度的字节,存入定义的数组中,再通过然后再通过read()方法读取数组中的元素,存入缓冲区
2)循环这个动作,知道最后取出一组数据存入数组,可能数组并未填满,同样也取出包含的元素
3)每次取出的时候,都有一个指针在移动,取到数组结尾就自动回到数组头部,这样指针在自增
4)取出的时候,数组中的元素再减少,取出一个,就减少一个,直到减到0即数组取完
5)到了文件的结尾处,存入最后一组数据,当取完数组中的元素,就会减少到0,这是全部数据就取完了
示例:
/*通过缓冲区,演示Mp3的复制BufferedOutputStreamBufferedInputStream*/import java.io.*;class CopyMp3{ public static void main(String []args) throws IOException { long start=System.currentTimeMillis(); //copy_1(); copy_2(); long end=System.currentTimeMillis(); System.out.println((end-start)+"毫秒"); } //通过字节流的缓冲区,完成复制 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(); } public static void copy_2() throws IOException { MyBufferedInputStream bufis=new MyBufferedInputStream(new FileInputStream("C:\\0.mp3")); BufferedOutputStream bufos=new BufferedOutputStream(new FileOutputStream("C:\\2.mp3")); int by=0; //读了一次没有写出去 // System.out.println("第一个字节:"+bufis.myRead()); while((by=bufis.myRead())!=-1) { bufos.write(by); } bufos.close(); bufis.myClose(); }}
4、自定义字节流缓冲区:
思路:
1、定义一个固定长度的数组
2、定义一个指针和计数器用于读取数组长度,和计数数组元素是否取完为0
3、每次将字节数据存入元素要先将数组中的元素取完
注:取出的是byte型,返回的是int型,这里存在提升的动作,
当byte中的八位全为1的时候是byte的-1,提升为int类型,就变为int型的-1,,read循环条件就结束了
变为-1的原因是由于在提升时,将byte的八位前都补的是1,即32位的数都是1,即为int型的-1了。
如何保证提升后的最后八位仍为1呢?就需要将前24位补0,就可以保留原字节数据不变,又可以避免转为int型出现-1的情况;
那么要如何做呢?
示例:
/*11111111 -->提升了一个int类型,那不还是-1,吗?是-1的原因是因为在8个1的前面补得的是1导致的那么我只要在前面补0,既可以保留原字节数据不变,又可以避免-1的出现,那么怎,补0呢 11111111 11111111 11111111 11111111&00000000 00000000 00000000 11111111------------------------------------- 00000000 00000000 00000000 11111111 这样就可以避免-1的发生 byte:-1 ---->int:-1 read方法在提升,write方法将指定的字节写入此缓冲的输出流(强制转换,取最低的8位)*/import java.io.*;class MyBufferedInputStream{ private InputStream in; private byte[] buf=new byte[1024*4]; private int pos=0; private int 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; //取数组第一个元素pos=0; byte b=buf[pos]; count--; pos++; //b与255进行与操作,用十六进制表示就是0xff return b&255; }else if(count>0) { byte b=buf[pos]; count--; pos++; //b与255进行与操作,用十六进制表示就是0xff return b&255; } return -1; } public void myClose()throws IOException { in.close(); } }5.读取键盘录入
System.out:对应的是标准的输出设备,控制台。
System.in:对应的标准输入设备,键盘
/*需求:通过键盘录入数据,当录入一行数据后就进行打印。如果当录入的数据时over,那么停止录入Dos下键盘录入操作终止可以使用Ctrl+C操作*/import java.io.*;class ReadIn{ public static void main(String[] args) throws IOException { InputStream in=System.in;StringBuilder sb=new StringBuilder(); /*int ch=0; while((ch=in.read())!=-1) { System.out.println(ch);}*/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=new StringBuilder(); sb.delete(0,sb.length());}elsesb.append((char)ch);}in.close();//数据类型转换System.out.println('\r'+0);System.out.println('\n'+0);/*int by=in.read();int by1=in.read();int by2=in.read();System.out.println(by);System.out.println(by1);System.out.println(by2);*/ }}
知识点三 转换流
一、概述:
转换流的由来:内部可以指定编码表
1.通过上面的示例,通过键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理
能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流BufferedReader类中的方法
而键盘录入的read方法字节流InputStream的方法
那么能不能将字节流转成字符流在使用字符流缓冲区的readLine方法呢?
2.两个转换流:读取转换流InputStreamReader和写入转换流OutputStreamWriter,这两个类分别属于字符流Reade和Writer的子类
二、读取转换流:
InputStreamReader是字节流通向字符流的桥梁,它使用指定的charset读取字节并将其解码为字符。
InputStreamReader:读取转换流
a.获取键盘录入对象: ---> InputStream in = System.in;
b.将字节流对象转换成字符流对象,使用转换流InputStreamReader: ---> InputStreamReader isr = new InputStreamReader(in);
c.为提高效率,将字符串进行缓冲区技术操作,使用BufferedReader: ---> BufferedReader bufw = new BufferedReader(isr);
d.之后就可以使用readLine()方法读取录入的一行数据了。
示例:
class TransStreamDemo{ public static void main(String []args) throws IOException { //获取键盘录入对象 // InputStream in=System.in; //将字节流对象装换成字符流对象,InputStreamReader //InputStreamReader isr=new InputStreamReader(in); //为了提高效率,讲将字符流进行缓冲区技术的高效操作 // BufferedReader bufr=new BufferedReader(isr); BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("CopyMp3.java"))); BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out)); String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; System.out.println(line.toUpperCase()); } bufr.close(); }}
OutputStreamWriter是字符流通向字节流的桥梁,可使用指定的charset将要写入流中的字符编码成字节。
OutputStreamWriter:写入转换流 ---> 和读取转换流同理,即使用对应的Writer的子类
示例:
class TransStreamDemo{ public static void main(String []args) throws IOException { //*************毕老师说这句换一定要记住,键盘录入,非常的重要******************** //键盘录入最常见写法 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(); }}
知识点四 流操作规律
一、分析清楚源和目的以及需求:
1.源:键盘录入
目的:控制台
2.需求:想把键盘录入的数据存储到一个文件中
源:键盘
目的:文件
3.需求:想要将一个文件的数据打印在控制台上。
源:文件
目的:控制台
二:流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个
通过三个来明确
1.明确源和目的
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
2.明确操作的数据是否是纯文本
是:字符流
不是:字节流
3.当体系明确后,在明确要使用哪个具体的对象
通过设备来进行区分;
源设备:内存(ArrayStream),硬盘(FileStream),键盘(System.in)
目的设备:内存(ArrayStream),硬盘(FileStream),控制台(System.out)。
4、需求体现:
4.1需求:将一个文本文件中的数据存储到另一个文件中,复制文件。
源:因为是源,所以使用读取流 InputStream Reader
是不是操作文本文件?
是!这时就可以选择Reader
这样体系就明确了
接下来明确对象该体系中的哪个对象。
明确设备:硬盘上的一个文件。
Reader体系中可以操作文件的对象是FileReader
是否需要提高效率:是!加入Reader体系中的缓冲区,BufferedReader
FileReader fr=new FileReader("a.txt");
BufferReader bufr=new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本文件?
是!Writer。
设备:硬盘。一个文件。
Writer体系中可以操作文件的对象是FileWriter
是否需要提高效率:是!加入Writer体系中的缓冲区,BufferedWriter
FileWriter fw=new FileWriter("b.txt");
BufferedWriter bufw=new BufferedWriter(fw);
练习:将一个图片文件中数据存储到另一个文件中,复制文件。要按照以上格式完成三个明确。
分析:
1)源:InputStream和Reader
图片:字节流 ---> InputStream
设备:硬盘上的文件 ---> FileInputStream
2)目的:OutoutStream和Writer
图片:字节流 ---> OutputStream
设备:硬盘上的文件 ---> FileOutputStream
4.2需求:将键盘录入的数据保存到一个文件中
这个需求中有源和目的都存在。
那么分别分析
源: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);
目的:OutputputStream Writer
是否是纯文本?是!Writer
设备:硬盘。一个文件。使用FileWriter
FileWriter fw=new FileWriter("c.txt");
需要提高效率吗?需要
BufferedWriter bufw=new BufferedWriter(fw);
5.扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中
class TransStreamDemo2{ public static void main(String []args) throws IOException { //获取键盘录入对象 // InputStream in=System.in; //键盘录入最常见写法 BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d2.txt"),"UTF-8")); String line=null; while((line=bufr.readLine())!=null) { if("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); }}6.改变标准输入输出设备
System.setIn(new FileInputStream("PersonDemo.java"));
System.setOut(new PrintStream("zz.txt"));
一、异常的日志信息:
当程序在执行的时候,出现的问题是不希望直接打印给用户看的,是需要作为文件存储起来,方便程序员查看,并及时调整的。
示例:/*说明:Log4j的jar包可以完成日志信息建立*/import java.io.*;import java.util.*;//格式化要用的包import java.text.*;class ExceptionInfo{ public static void main(String[] args) throws IOException { try{ int[] arr=new int [2]; System.out.println(arr[3]); }catch(Exception e){try{ //打印日期 Date d=new Date(); //SimpleDateFormat将时间格式化 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//h是12小时制,H是24小时制 String s=sdf.format(d); PrintStream ps=new PrintStream("exception.log"); //ps是字节流,要将字符串变成字节数组写出去 //ps.write(d.toString().getBytes); //ps.println(d.toString()); ps.println(s); //改变标准输出 System.setOut(ps); //e.printStackTrace(new PrintStream("a.txt"));}catch(IOException ex){ throw new RuntimeException("日志文件创建失败");} e.printStackTrace(System.out);} } }
二、系统信息:
获取系统信息:Properties getProperties()
将信息输出到指定输出流中
void list(PrintStream out)
将输出流中数据存入指定文件中
new PrintStream("systeminfo.txt")
import java.io.*;import java.util.*;class SystemInfo{ public static void main(String[] args) throws IOException { //打印系统信息 //源就是集合中的数据也就是内存 Properties prop=System.getProperties(); //System.out.println(prop); //将系统信息打印在控制台上 //prop.list(System.out); prop.list(new PrintStream("sysinfo.txt")); }}
最新最全的的java学习视频教程:http://pro.net.itcast.cn/View-22-1458.aspx
详细请查看:http://edu.csdn.net/heima
- 黑马程序员 java基础<四>--IO流(2)
- 黑马程序员---Java基础--21天(IO流之四)
- 黑马程序员 Java基础----IO流(2)
- 黑马程序员-----Java基础-----IO流-2
- 黑马程序员——Java基础--IO(四)
- 黑马程序员-java基础 io字符流
- 黑马程序员-java基础 io字节流
- 黑马程序员--JAVA基础之IO流
- 黑马程序员JAVA基础-IO流
- 黑马程序员 Java基础 ---> IO流
- 黑马程序员 JAVA基础<五> IO流
- 黑马程序员-JAVA基础-IO流
- 黑马程序员 java基础回顾---IO流
- 黑马程序员---java基础---5IO流
- 黑马程序员----Java基础之IO流
- 黑马程序员---Java基础总结--IO流
- 黑马程序员-java基础-IO流
- 黑马程序员--JAVA基础之IO流
- 自定义listview,支持上拉下拉刷新,暴露出接口,自带demo
- 使用Struts 拦截namespace进行权限控制
- 灵飞经4·西城八部 第十六章 风流云散 5
- java学习笔记---构造器的多态和调用顺序
- aaa
- 黑马程序员 java基础<四>--IO流(2)
- linux 下UDP通信(附加测试代码)
- poj1032
- How OpenStack Should Prepare Itself for the Enterprise
- hdu 1142 A Walk Through the Forest
- TCP三次握手及四次挥手详细图解
- 灵飞经4·西城八部 第十六章 风流云散 6
- 集合
- putty长连接不断线方法和乱码处理