黑马程序员-Java学习09-IO类2

来源:互联网 发布:移动网络电视打不开 编辑:程序博客网 时间:2024/05/20 20:19

-----------android培训java培训、java学习型技术博客、期待与您交流!------------


1.带有行号的缓冲区:
LineNumberReader lnr=new LineNumberReader();
获取行号:lnr.getLineNumber();
设置行号从几开始:lnr.setLineNumber(100);
LineNumberReader 步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
LineNumberReader lnfr=new LineNumberReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=lnfr.readLine())!=null)
{
String s=line;
String linenum=lnfr.getLineNumber();
}
4.关闭

lnfr.close();
扩展:自写LineNumberReader类

public class MyLineBufferReader extends MyBufferedReader {public MyLineBufferReader(Reader r) {super(r);}private int LineNumber;public int getLineNumber() {return LineNumber;}public void setLineNumber(int lineNumber) {LineNumber = lineNumber;}public String myReadLine() throws IOException{LineNumber++;return super.myReadLine();}}

2.字节流:

InputStream  OutputStream

需求,想要操作图片数据。这时就要用到字节流。字节流读写的是byte[]数组,字符流动读写的是char[]

复制一个图片.

import java.util.*;import java.io.*;public class CopyPic {         public static void main(String[] args)throws IOException {                   copyPic();         }         public static void sop(Object obj){                   System.out.println(obj);         }         public static void copyPic()throws IOException{                   FileInputStream fip = new FileInputStream("a.jpg");                   FileOutputStream fop = new FileOutputStream("d.jpg");                   byte[] by = new byte[1024];                   int num;                   long time1 =System.currentTimeMillis();                   while ((num = fip.read(by)) != -1) {                            fop.write(by,0,num);                   }                   fip.close();                   fop.close();                   long time2 =System.currentTimeMillis();                   sop(time2-time1);          }}

利用BufferedInputStream 复制mp3

import java.io.*;public class CopyMp3  {         public static void main(String[] args)throws IOException {                   copy();         }         public static void copy()throws IOException{                   BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.mp3"));                   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.mp3"));                   byte[] by = new byte[1024];                   int num = 0;                   while ((num = bis.read(by))!=-1) {                            bos.write(by);                   }                   bis.close();                   bos.close();         }}


重写myRead()方法
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;// &255防止误提升为-1}else if(count>0){byte b = buf[pos];count--;pos++;return b&0xff;}return -1;}public void myClose()throws IOException{in.close();}}/*11111111-111111110000000000101001001010100101010010101001010byte: -1  --->  int : -1;00000000 00000000 00000000 11111111  25511111111 11111111 11111111 1111111111111111  -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。怎么补0呢? 11111111 11111111 11111111 11111111                        &00000000 00000000 00000000 11111111 ------------------------------------ 00000000 00000000 00000000 11111111 0000-00011111-11100000000011111-1111  -1结论:字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。*/


3.转换流

读取转换流:InputStreamReader

写入转换流:OutputStreamReader

读取转换流:InputStreamReader 字节流通向字符流的桥梁

步骤

1.获取键盘录入对象

Inputstream in=System.in

2.将字节流对象转换成字符流对象,使用转换流InputStreamReader

InputStreamReader isr=new InputStreamReader(in);

3.提高效率使用字符流缓冲区 BufferedReader进行读取

BufferedReader bf=new BufferedReader(is);

String line=null;

while((line=bf.readLine())!=null)

{

    if("over".equals(line))

     break;

    sop(line);

}

bufr.close;

写入转换流:OutputStreamReader 字符流通向字节流的桥梁

步骤

1.获取输出对象

Outputstream out=System.out

2.将字符流对象转换成字节流对象,使用转换流OutputstreamWriter

OutputstreamWriter osw=new OutputstreamWriter(out);

3.提高效率使用字符流缓冲区 BufferedWriter进行写入

BufferedWriter bw=new BufferedWriter(osw);

String line=null;

while((line=bf.readLine())!=null)

{

    if("over".equals(line))

     break;

    bw.write(line);

    bufw.newLine();

}

bufr.close;


键盘的最常见写法。

  BufferedReader bufr =

    new BufferedReader(new InputStreamReader(System.in));

注:转换流可以指定编码格式

4.流操作基本规律:
两个明确:
1.明确源和目的
   源:输入流。InputStream字节流  Reader 字符流
   目的:输出流 OutPutStream 字节流  Writer 字符流
 2.操作的数据是否是纯文本
   是 就是字符流 如果设备是键盘 就将字节流转换为字符流
   不是 就是 字节流
3.当体系明确后,在明确要是用那个具体的对象
    通过设备来区分 
     源设备  内存 硬盘 键盘
     目的设备  内存  硬盘  控制台
4.是否需要提高效率  是 BufferedReader  BufferedInputStream
                   否 BuffreredWriter BufferedOutputStream
案例分析 :
1.将一个文本文件中的数据存储到另一个文件中,复制文件
  源: InputStream字节流  Reader 字符流
  是否是纯文本 是  Reader
   设备: 文件   操作文件的对象 就是FileReader
  是否需要高效 
  是  BufferedReader
   FileReader fr=new FileReader("a.txt");
   BufferedReader bufr=new BufferedReader(fr);
 目的   OutPutStream 字节流  Writer 字符流
 是否是纯文本 :是 Writer 
 设备: 文件 写入文件的对象 就是 FileWriter 
 是否需要高效  是   BufferedWriter
  FileWriter fw=new FileWriter("b.txt");
   BufferedWriter bufw=new BufferedWriter(fw);

2.将一个图片文件数据存储到另一个文件中,复制文件。
分析
源:
 是否是纯文本 : 不是  InputStream
 设备 文件 就是 FileInputStream
  是否高效 是
 BufferedInputStream
   FileInputStream isr=new FileInputStream("a.jpg");
 BufferedInputStream bufis=new BufferedInputStream(isr);
目的
  是否纯文本 :不是 OutPutStream
  设备:文件 FileOutPutStream
是否高效 是
 BufferedOutputStream
 FileOutPutStream osw=new FileOutPutStream("b.jpg");
    BufferedOutputStream bufos=new BufferedOutputStream(osw);
 
3.扩展 :想要吧录入的数据按照指定的编码表(utf-8)将数据存到文件中
   目的:OutPutStream 字节流  Writer 字符流
   是否是存文本:是  Writer
   设备 :文件 fileWriter
   默认编码表是 gbk
   编码标只有转换流可以指定。所以要使用的对象是写入转换流 OutputStreamWriter
   转换流需要接受一个自己输出流,操作字节输出流的是FileOutputStream
   OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("b.txt"),"utf-8");
  BufferedWriter bufw=new BufferedWriter (osw);
通常涉及到字符编码转换的时候,就需要用到转换流。

练习:记录异常日志(涉及Date类)
   

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);}}}
练习二:保存系统信息
import java.util.*;import java.io.*;public class SystemInfo  {         public static void main(String[] args) throws Exception {                   Properties p = System.getProperties();                   PrintStream ps = new PrintStream("systemInfo2.txt");                   System.setOut(ps);                   // p.list(ps);                   Set set = p.keySet();                   // Iterator<String> it = set.iterator();                   for(Object obj:set){                            String value = (String)p.get(obj);                            sop(obj+"="+value);                   }         }         public static void sop(Object obj){                   System.out.println(obj);         }}


5.对象流

import java.io.*;class Person implements Serializable{// public static final long serialVersionUID = 42L;     // 如果标识唯一标识码,则不会改变private String name;transient int age;// transient 标记不会记录进去static String country = "cn";Person(String name,int age,String country){this.name = name;this.age = age;this.country = country;}public String toString(){return name+":"+age+":"+country;}}public class ObjectStreamDemo {public static void main(String[] args) throws Exception {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:\\object.txt"));ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:\\object.txt"));oos.writeObject(new Person("nuddles",34,"cn") );    Person p = (Person)ois.readObject();    sop(p);    oos.close();    ois.close();}public static void sop(Object obj){System.out.println(obj);}}

6.合并流

import java.io.*;import java.util.*;public class SequenceDemo  {public static void main(String[] args) throws IOException{Vector<InputStream> vector = new Vector<InputStream>();// Vector是一种枚举vector.add(new FileInputStream("d:\\1.txt"));vector.add(new FileInputStream("d:\\2.txt"));vector.add(new FileInputStream("d:\\3.txt"));vector.add(new FileInputStream("d:\\4.txt"));FileOutputStream out = new FileOutputStream("d:\\haha.txt");marge(vector,out);}public static void marge(Vector<InputStream> vector,OutputStream out) throws IOException{SequenceInputStream sis = new SequenceInputStream(vector.elements());byte[] by = new byte[1024];int len =0;while ((len=sis.read(by))!=-1) {out.write(by,0,len);out.flush();}sis.close();out.close();}}

7.RandomAccessFile

该类不是算是IO体系中子类。

而是直接继承自Object。

但是它是IO包中成员。因为它具备读和写功能。

内部封装了一个数组,而且通过指针对数组的元素进行操作。

可以通过getFilePointer获取指针位置,

同时可以通过seek改变指针的位置。

其实完成读写的原理就是内部封装了字节输入流和输出流。

通过构造函数可以看出,该类只能操作文件。

而且操作文件还有模式:只读r,,读写rw等

如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。

如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。

import java.io.*;import java.util.*;public class RandomAccessFileDemo  {         public static void main(String[] args) throws IOException{                   write();         }         public static void sop(Object obj){                   System.out.println(obj);         }         public static void write() throws IOException{                   RandomAccessFile raf = new RandomAccessFile("d:\\nuddles.txt","rw");                   raf.write("this is my file".getBytes());                   raf.skipBytes(8);                   raf.writeInt(56);                   raf.seek(0);                   // 读之前要跳回到0指针处                   byte[] by = new byte[1024];                   raf.read(by);                   String s = new String(by);                   sop(s);                   raf.close();         }}

8.DataInputStream与DataOutputStream

可以用于操作基本数据类型的数据的流对象。

有相应读写各种类型的方法,特殊方法:readUTF/writeUTF


9.用于操作字节数组的流对象。

ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。

ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。

这就是数据目的地。

因为这两个流对象都操作的数组,并没有使用系统资源。

所以,不用进行close关闭。

在流操作规律讲解时:

源设备,

 键盘 System.in,硬盘 FileStream,内存 ArrayStream。

目的设备:

 控制台 System.out,硬盘FileStream,内存 ArrayStream。

用流的读写思想来操作数据。

import java.io.*;class ByteArrayStream{         public static void main(String[] args)         {                   //数据源。                   ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());                    //数据目的                   ByteArrayOutputStream bos = new ByteArrayOutputStream();                    int by = 0;                    while((by=bis.read())!=-1)                   {                            bos.write(by);                   }                    System.out.println(bos.size());                   System.out.println(bos.toString());}

-----------android培训java培训、java学习型技术博客、期待与您交流!------------


  


































  
  


0 0
原创粉丝点击