Java中的IO操作

     IO 操作是我以前不太理解的操作。总是觉得很神奇,然后一脸懵逼。今天终于鼓起勇气,认真的学习IO方面的知识。有理解不妥当或者不正确的地方,还请各位大佬指正。

一、java的io发生在哪?

      这个问题,我们必须首先明确下。io发生在内存和硬盘之间。因为程序在内存中运行。我们需要将硬盘的文件数据读入到内存中,再将数据从内存输出到硬盘中,所以我们就有了IO操作。i和o是分别代表(input和output)。输入和输出,都是我们站在内存的角度看的。不要弄混了哦。

二、java中的IO类

在提IO具体类之前,我们需要先了解下文件类,因为我们需要从硬盘的文件读入流数据或者写出流数据。所以我们需要先让我们的一个对象指定对应的文件。

java中的IO类主要分为两大类:节点流类和处理流类。下边我来分别讲述这两类中的流类.

  1.java中的节点流:节点流分为字节流和字符流。

           (1)字节流为FileInputStream(输入)和FileOutputStream(输出)两个类。在字节流中,我们通常用字节数组(byte[ ])来作为运输这些字节流的载体。

           (2)字符流为FileReader(读入)和FileWriter(写出)两个类。在字符流中,我们通常用字符数组(char[ ])来作为运输这些字节流的载体。

            (3)看一个例子的代码实现(读入和写出字符的,输入和输出字符的同理)。

public void oop11() {
File iipp = new File("C:\\Users\\er\\Desktop\\2.txt");     //在这,我们使得iipp这个对象关联C:\\Users\\er\\Desktop\\2.txt这个文件。必须要用双斜杠哦,因为单斜杠是转义字符。
File iipp1 = new File("C:\\Users\\er\\Desktop\\5.txt");            //如果有,就关联,没有就先创建后再关联(有输出流的方法中)。
FileReader fr = null;
fr1 = null;
try {
         fr = new FileReader(iipp);                      //在这我们创建读入2.txt的字符流对象

fr1 = new FileWriter(iipp1);                     //在这我们创建输出到5.txt的字符流对象

                        char[ ] kk = new char[25];                        //创建char类型的数组,用来运输字符

int len;                                                   

while ((len = fr.read(kk)) != -1) {            //参考javaApi中描述:read方法返回值为:The character read, or -1 if the end of the stream has been reached (读入的字母或者当到达流的末尾后返回-1),所以我们用while函数,当它不能于-1时,就一直读。

  fr1.write(kk, 0, len);             //写出数组中从第0个开始到第len个(因为我们已经读了这么多呀。)          
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();

}

             finally {if(fr!=null && fr1!=null) {            //如果这两个流都为null,则说明没有进行流的赋值,则需要重新赋值,不能关闭。如果为null,则说明我们上边的程序已经执行完毕。用完流后,需要将流关闭。

                      try {
fr.close();                      // 关闭输入和输出流,关闭的先后顺序无所谓。  
fr1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();

}
}}
}

       做个比喻,当我们用字节流或者字符流时,我们相当于在内存和硬盘中的文件(File形参)之间搭起了一座单向的路,同时这个路有相关的路政机构(流类中的方法),他们在硬盘与内存的接口,负责数据的读写工作。通常情况下,我们选择用数组来装载运输数据,就像大卡车一样运输货物一样。我们根据目标文件的大小来选择卡车的大小(byte或者char数组的长度),输出到控制台或者文件中。就像下图描述的这样。

 

2..java中的处理流:很多。在这我们只说两种处理流:缓冲流(能大幅增加程序读写文件的效率)和对象流(这个流给我的感觉就是很可爱,我也不知道为啥是这种感觉~)。

   (1)缓冲流:先看java API中的定义:When the BufferedInputStream is created, an internal buffer array is created. As bytes from the stream are read or skipped, the internal buffer is refilled as necessary from the contained input stream, many bytes at a time.(当创建了缓冲流时,我们也就创造了一个额外的缓冲区。当流中的字节被读或者转移的时候,这个缓冲区就被填充满,一次可以填充很多字节)。另补充下,缓冲区位于内存之中,在java中大小一般为8M,这样我们一次就可以读入或者输出8m的字节,相比于一次一个数组,我们肯定快了许多。内存和内存之间的传输相比于内存与硬盘的传输也快了许多。

    (2)缓冲流的分类:BufferedInputStream/ BufferedOutputStream 类(字节的输入输出)和BufferedReader/ BufferedWriter(字符的输入输出)类。接下来我们仍然需要看代码实现。

     public void oop12(String dec,String hh) {

File iipp1=new File(dec);      //此处dec和hh都为包含路径的文件名
File iipp3=new File(hh);
FileInputStream uup=null;              //初始化字节的输入输出及缓冲流为null
BufferedInputStream aa=null;
FileOutputStream uup2=null;
BufferedOutputStream aa2=null;
try {
uup=new FileInputStream(iipp1);          //将字节输入流搭在dec文件上(换种说法就时是创建dec文件到内存的流)
aa= new BufferedInputStream(uup);     //创建uup的缓冲流(缓冲流只能建立在节点流之上,不能直接接在文件上)
uup2=new FileOutputStream(iipp3);      
aa2= new BufferedOutputStream(uup2);
byte[]  yy=new byte[200];                        //创建字节数组
int len;
while((len=aa.read(yy))!=-1) {               
aa2.write(yy,0,len);
                       aa2.flush();                               //将缓冲区的数据强行冲到文件中,之所以有这个函数,是担心有缓冲区的数据没有被输出,导致数据丢失。

}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
if (aa!=null&&  aa2!=null) { 
  try {aa2.close();

     aa.close();                     //只需要关闭Buffer的流就行了,关闭它,就已经关了节点流。

                     aa2.close();

 } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}}

}

综上,我们仍然可以画个图来表示这个过程。


当我们读入这个文件时,我们会首先创建个缓冲区,这个缓冲区一次从流中读入8M数据到内存(java中通常设置),

然后我们再通过数组对缓存中的数据进行读取。当我们要写出文件时,我们会首先创建个缓冲区,然后通过数组的形

式写到这个缓冲区里,等缓冲区到了8M,直接送出内存到硬盘。就像我们单独用节点流,每次都只转移一个数组的

数据,通过缓冲,我们一次转移8M。效率会大大增加。就像我们最开始是用卡车来回运输货物,现在开始用卡车先

装到距离我们最近的航空母舰上,(额,远洋货轮上),再送,效率肯定会有很大提升。

(3)对象流:之所以谈这个流,是觉得这个流特别有意思。来先看API:An ObjectOutputStream writes

primitive data types and graphs of Java objects to an OutputStream. The objects can be read (reconstituted

) using an ObjectInputStream. Persistent storage of objects can be accomplished by using a file for the

stream. If the stream is a network socket stream, the objects can be reconstituted on another host or in

another process. (一个输出的对象流输出原始的数据类型和对象的结构,我们可以用输入对象流来读这个对象,

如果想永久的保存的话,我们可以将它保存到一个文件中,如果这个流是网络套接字流的话(网络传输),我们可

以再另一台主机或者进程中将其再生(重新使用))。就是说我们通过这个对象流,可以保存、输入、输出我们一个类

的对象!很好玩的事情,虽然我目前还不知道具体应用。来继续看其代码实现。

       class  ooo implements Serializable {  //在这我们造了类,后边实现Serializable(序列化),没有序列化,就不能使用对象流。
Integer a=5;                       //类中不能有static(静态的)和transient (短暂的)关键字修饰的变量
       @Override
public String toString() {
return "ooo [a=" + a + "]";
}

}

public class io2 {
public void testobject() {
ooo u=new ooo();
ObjectOutputStream oos=null;
ObjectInputStream ooss=null;
try {
oos = new ObjectOutputStream(new FileOutputStream("ss.txt")); //我们将输出流搭在ss.txt(相对路径)
oos.writeObject(u); //写入u对象
oos.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {if(oos != null) {
try {
oos.close(); //关闭流
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}}}
}

3.需要注意的一点:流用完之后记得关闭。要不然会造成内存和cpu性能的浪费,甚至硬盘的数据填满。

over~,这次就这些喽。周末愉快,小宝贝们。

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值