------- android培训、java培训、期待与您交流! ----------
字节流——OutputStream和InputStream
一、FileOutputStream
1、简介:文件输出流是用于将数据写入
File
或FileDescriptor
的输出流。文件是否可用或能否可以被创建取决于基础平台。特别是某些平台一次只允许一个FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。FileOutputStream
用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用FileWriter
2、构造方法:
1、FileOutputStream(File file):根据给定的 File 对象构造一个FileOutputStream对象。
2、FileOutputStream(File file, boolean append) :根据给定的 File 对象构造一个 FileOutputStream对象,当append为true为真时,则是在给定的File对象后面添加。
3、FileOutputStream(FileDescriptor fd) :构造与某个文件描述符相关联的FileOutputStream对象
4、FileOutputStream(String fileName) :根据给定的文件名构造一个FileOutputStream对象
5、FileOutputStream(String fileName, boolean append):根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileOutputStream 对象。
3、字节流的写入:
1、导入java.io包。
2、创建一个FileOutputStream(写入字符流)对象,该对象只有自己特有的构造方法用于创建对象。在创建该对象时必须指定要操作的文件。该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。实际上该步就是在明确操作的对象。
3、调用public void write()方法,将要写入的数据写入到流中。
4、如果是最后一次写入数据,则可以public void close()方法,将流中的数据刷到目标文件中,并且在刷新后关闭该流。
注:在建立写入字节流对象,操作完成后必须调用close方法关闭流对象。在字节流的写入和字符流有所不同。字节流写入是直接写入到目标文件,而不用flush()操作。
二、FileInputStream
1、简介:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。
FileInputStream
用于读取诸如图像数据之类的原始字节流。2、构造方法:
1、FileInputStream(File file) :在给定从中读取数据的File 的情况下创建一个新FileInputStream。
2、FileInputStream(FileDescriptor fd):在给定从中读取数据的FileDescriptor 的情况下创建一个新FileInputStream。
3、FileInputStream(String fileName) :在给定从中读取数据的文件名的情况下创建一个新FileInputStream。
3、文件的读取:通过InputStream中的read()方法,以及它的重载方法。
三、图像文件的拷贝:
1、将I:\\Important\\IMG_0002.jpg文件拷贝是d盘的根目录下。
代码示例:
import java.io.*; class CopyPic { public static void main(String[] args) throws IOException { FileOutputStream fo = new FileOutputStream("d:\\IMG_0002.jp"); FileInputStream fi = new FileInputStream("I:\\Important\\IMG_0002.jpg"); byte[] buf = new byte[1024]; for (int flag=fi.read(buf);flag!=-1 ;flag=fi.read(buf) ) { fo.write(buf,0,flag); } } }
四、字节流的缓冲区:
1、原理:和字符流缓冲区的原理是一样的。
代码:
2、缓冲区对字节处理的一些技巧:import java.io.*; class CopyMp3 { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); copy_mp3(); long end = System.currentTimeMillis(); System.out.println("复制完成,用时:"+(end-start)+"毫秒"); } public static void copy_mp3()throws IOException { BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("d:\\1\\混合1.mp3",true)); BufferedInputStream bi = new BufferedInputStream(new FileInputStream("D:\\BaiDuMusic\\风儿啊!请你停下来.mp3")); for (int flag=bi.read();flag!=-1 ;flag=bi.read() ) { bo.write(flag); } } }
1、字节流的读取是读取一个字节(8个二进制位),当这个字节的八个位都为1的时候,计算机就会认为是-1。为了解决这个问题,就把这个读取的一个字节用int类型进行接收。为了使八位二进制数表示的是正数,则在返回的这个字节低八位为int数的低八位,其余的加0;方法是return byte&255;
2、当将byte提升为int类型后,1个字节变成了4歌字节,则是原文件增加了4倍。因此在Writer方法中又将此数据进行强转,使之仍然是八个位。
3、简易缓冲区定义的代码:
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; } return -1; } public void myClose()throws IOException { in.close(); } }
1、原理:之前我 们处理的数据的时候都是先建立和文件相关的流。那怎么从处理从键盘输入的数据呢?处理原理都是一样的,唯一不同的是我们之前要建立相关的流去读取原文件,现在的流是从键盘的录入读取而已。即用System,in;去代替原来的输入流对象。2、 从键盘输入流的建立: InputStream in = System.in;通过前面学过的System类去建立这个对象。3、 处理:
1、处理方式和原来处理的方式一样。2、代码:
import java.io.*; class ReadIn { public static void main(String[] args) throws IOException { //建立从键盘输入的流 InputStream in = System.in; //建立键盘输入的字符串的存储区 StringBuilder sb = new StringBuilder(); //建立流对象输出的对象流 BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\gh\\aba.txt",true)); //读取从键盘输入的数据 for (int flag=in.read();flag!=-1 ;flag=in.read() ) { if (flag=='\r') { if (in.read()=='\n') { String s = sb.toString(); //处理方式一:将从键盘输入的数据在屏幕上打印输出 System.out.println(s); //处理方式二:把从键盘输入的数据分行的存在文本文件中 bw.write(s); bw.newLine(); bw.flush(); //判断是否该结束循环条件一 if ("over".equals(s)) { break; } //判断是否结束循环的条件二 String sb1 = sb.substring((sb.length()-4),sb.length()); sb.delete(0,sb.length()); if("over".equals(sb1)) break; } //暂存从键盘输入的数据 else { sb.append((char)'\r'); sb.append((char)flag); } } else { sb.append((char)flag); } } //关闭流 bw.close(); in.close(); } }
二、转换流——InputStreamReader:
1、简介:InputStreamReader 是字节流通向字符流的桥梁:它使用指定的
charset
读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集2、作用:在上面获取从键盘上键入的数据时我们只能一个一个的获取,我们还可以用通过转换流。将这个字节输入流转化成字符输入流。使之能读取一行的数据。
3、InputStreamReader的使用:
1、建立字节输入流。
2、通过InputStreamReader的构造函数,将字节流输入流传入InputStreamReader中。
3、此时的使用和字符输入流一样。
4、代码示例:
三、转换流——OutputStreamWriter要求:1、将从键盘输入的字符使用字符流的操作将其存贮在文本文件中
代码:
import java.io.*; class ReadIn1 { public static void main(String[] args) throws IOException { //建立从键盘输入的流 InputStream in = System.in; //建立字符输入缓冲流和字符输出缓冲流 BufferedReader br = new BufferedReader(new InputStreamReader(in)); BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\1\\InputStreamReader.txt",true)); //建立流对象输出的对象流 for (String s=br.readLine(); s!=null; s=br.readLine()) { bw.write(s); bw.newLine(); bw.flush(); //定义结束的条件 if (s.length()>=4) { String s1 = s.substring(s.length()-4,s.length()); if ("over".equals(s)||"over".equals(s1)) { break; } } } } }
1、简介:OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的
charset
将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。2、作用:将输出流转化成操作字符的输出流对象。
3、OutputStreamWriter的使用:
1、建立字节输入流。
2、通过InputStreamWriter的构造函数,将字节流输入流传入InputStreamWriter中。
3、此时的使用和字符输出流一样。
4、示例:
目的:把从键盘录入的数据保存在文本文件里。
当末尾以over字符串结束则停止录入
代码:
import java.io.*; class KeyBoard { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\1\\hm1.txt")); BufferedWriter bw1 = new BufferedWriter(new OutputStreamWriter(System.out)); for (String s = br.readLine(); s!=null; s=br.readLine()) { bw.write(s); bw.newLine(); bw.flush(); bw1.write(s); bw1.newLine(); bw1.flush(); if (s.length()>=4) { String s1=s.substring(s.length()-4,s.length()); if ("over".equals(s1)) { break; } } } br.close(); bw.close(); bw1.close(); } }
四、流对象操作规律
1、明确源和目的
源:输入流——>用InputStream、Reader
目的:输出流——>用OutputStream、Writer
2、操作数据是否是纯文本
是——>用字符流
不是——>用字节流
3、明确要使用的具体对象
通过设备来进行区分
源设备:内存、硬盘、键盘
目的设备:内存、硬盘、控制台
4、例如:拷贝一个纯文本文件。
明确源:为文件(使用读取流)——>为纯文本(用字符读取流)——>能操作文件的对象(FIieReader)
明确目的:写在硬盘上(写入流)——>文本(字符写入流)——>能操作文件的对象(FileWriter)
明确是否需要优化:要——>建立该流的缓冲对象,通过该对象去操作。
5、字节流到字符流的转换
如果字节流操作的是文本文件的时候我们可以通过OutputStreamWriter和InputStreamReader将其转换成字符流进行操作。
InputStreamReader类
InputStreamReader通过构造方法将字节流转换为字符流。并且在转换的时候可以制定编码表,如一个以UTF-8编码的文本文档,必须通过指定编码表才能将其打开。转换后的操作与操作字符流一样
6、改变标准输入输出设备:
在System类中提供了改变标准输入输出的方法。
setIn(InputStream in):将标准的输入设备设置成我们需要的设备。即改变System.in的对象。默认是键盘输入。
setOut(OutputStream out):将标准的输出设备设置成我们需要的设备。即改变System.out的对象。默认是答应在控制台。
7、异常的日志信息
1、在异常类中异常信息通过printStackTrace() 方法将信息打印在控制台上。这个方法实际是在执行printStackTrace(System.out)将异常信息输出在标准输出设备上。所以我们通过System类中提过的改变标准输出设备 的方法使之将该信息记录在文本文件中。当然也可以新建一个printedStream("a.txt")对象,去替代System.out对象。
2、打印异常的时间
建立util包中的Date对象,在通过text包中的SimpleDateFormat将时间格式化。
3、也可以通过log4j这个包建立日志信息。
4、示例:
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 sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String s = sdf.format(d); PrintStream ps = new PrintStream("exeception.log"); ps.println(s); System.setOut(ps); } catch (IOException ex) { throw new RuntimeException("日志文件创建失败"); } e.printStackTrace(System.out); } } }
8、Propertites中方法与流相结合
该类中有一个方法void list(PrintStream out):将属性列表输出到指定的输出流。即我们可以通过System类中getProperties()方法获取系统属性信息,然后利用list方法将其答应,或者通过list方法将其记录在文件中。
示例:
import java.util.*; import java.io.*; class SystemInfo { public static void main(String[] args) throws IOException { Properties prop = System.getProperties(); //System.out.println(prop); prop.list(new PrintStream("sysinfo.txt")); } }