【黑马程序员】IO流的几个问题

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

为什么在IO流的读写中,都初始化字节数组为1024长度

int length;
char[] arr = new char[1024];
while ((length = in.read(arr)) !=-1){
    out.write(arr,0,length);
}

这个字符数组其实就像所谓的缓冲区,每进行一次循环就覆盖一次数组内容.用数组来读取,仅仅是为了一块一块的读文件,而不是在某个时刻为文件分配内存,并且这样做能有效减少内存溢出的可能性.至于大小为什么是1024,1024代表1kb的数据,一次读取1kb,通常都这么设置,当然也可以设置成别的,但最好是1024的倍数.

为什么关闭输出流前要flush()

数据是先在缓冲中的,flush()方法可以强迫输出流(或缓冲的流)执行写入或发送,即使此时缓冲区还没有填满,这样可以避免没写入或者发送数据的尴尬

flush() 与close()的区别?
close()是关闭流,关闭前会刷新缓冲区,关闭后流对象不能继续使用
flush()仅仅是刷新,还可以继续使用流.

FileInputStream 和 FileReader区别

前置是用于二进制数据,即各种格式
后者仅仅适用于txt文本格式
BufferedReader 和 BufferedInputStream同理

InputStreamReader 和 FileReader区别

前者是转换流,可以指定编码或者用默认的编码,可用于各种格式.构造方法需要new一个InputStream实现类对象
后者是只用于txt文本格式,不能指定编码,采用的是系统默认编码,构造方法只需传入路径字符串
考虑到编码问题,建议用InputStreamReader

IO流总结

  1. 字节流

    • 字节输入流
      InputStream 读取二进制数据
      int read():一次读取一个字节
      int read(byte[] bys):一次读取一个字节数组

           FileInputStream
           BufferedInputStream
      
    • 字节输出流
      OutputStream
      void write(int by):一次写一个字节

          FileOutputStream
          BufferedOutputStream
      
  2. 字符流

    • 字符输入流
      Reader 读取文本数据
      int read():一次读取一个字符
      int read(char[] chs):一次读取一个字符数组

              InputStreamReader
                  |--FileReader
              BufferedReader
                  String readLine():一次读取一行数据,不包括换行符,如果到达某尾,返回null 效率低于一次读一个数组
      
    • 字符输出流
      Writer
      void write(int ch):一次写一个字符
      void write(char[] chs,int index,int len):一次写一个字符数组的一部分

              OutputStreamWriter
                  |--FileWriter
              BufferedWriter
                  void newLine():写一个换行符
                  void write(String line):一次写一个字符串
      

初学NIO

老师并没有讲太多NIO的东西,个人感觉NIO作为新事物,拥有远高于IO流的效率,那么一定是有很大用处的,于是翻阅了很多资料,大概的了解了一下NIO

最近一直使用 流 的方式完成 IO。所有 IO 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 IO 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。
NIO 与我们学习的 IO 有同样的作用和目的,但是它使用不同的方式, 块 I/O。块 I/O 的效率比流 I/O 高许多。

通道Channel 和 缓冲区Buffer

通道Channel 和 缓冲区Buffer 是 NIO 中的核心对象

通道Channel类似于原IO中的流。NIO中到任何目的地,或来自任何地方的所有数据都必须通过一个 Channel 对象。NIO中,我们不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动( InputStream ,OutputStream ), 而 通道 可以用于读、写或者同时用于读写。

缓冲区Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须先放到缓冲区中,从通道中读取的任何数据都要读到缓冲区中。

在IO中,数据是直接写入或者直接读到 Stream 对象中,而在NIO中,所有数据都是用缓冲区处理的.每一种基本数据类型都有一种缓冲区类型,每一个 Buffer 类都是 Buffer 接口的一个实例,他们方法都一样,只是处理的数据类型不一样.一般使用ByteBuffer

NIO中的基本操作

读取
四个步骤:
1. 从 FileInputStream 获取 Channel
2. 创建 Buffer
3. 将数据从 Channel 读到 Buffer 中。
4. 从Buffer中获取数据

示例如下:

RandomAccessFile aFile = new RandomAccessFile("copy.txt", "rw");
FileChannel inChannel = aFile.getChannel();//获取通道
ByteBuffer buf = ByteBuffer.allocate(48);//缓冲区大小定为48

int bytesRead = inChannel.read(buf); //写入数据到Buffer,返回读取的字节数
while (bytesRead != -1) {
    System.out.println( bytesRead); //打印读取了多少个字节
    buf.flip(); //反转缓冲区,将限制设为读取的字节数,位置设为0
    while(buf.hasRemaining()){  //开始从Buffer中读取数据
        char temp = (char) buf.get();//读取当前位置字节,然后位置递增
        System.out.print(temp); 
    }
    buf.clear();//清除缓冲区,位置设为0,限制设为容量
    bytesRead = inChannel.read(buf);//继续写入数据到缓冲区,直到写完,即返回-1为止
}
inChannel.close();
aFile.close();

当向 buffer 写入数据时,buffer 会记录下写了多少数据。如果要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式。在读模式下,可以读取之前写入到 buffer 的所有数据。

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。有两种方式能清空缓冲区:调用 clear() 或 compact() 方法。clear() 方法会清空整个缓冲区。compact() 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

示例2:把copy.txt复制到uio3.txt中
从通道到通道

RandomAccessFile fromFile = new RandomAccessFile("copy.txt", "rw");
FileChannel fromChannel = fromFile.getChannel();

RandomAccessFile toFile = new RandomAccessFile("uio3.txt", "rw");
FileChannel toChannel = toFile.getChannel();

long position = 0;
long count = fromChannel.size();
fromChannel.transferTo(position, count, toChannel);

fromChannel.close();
toChannel.close();
fromFile.close();
toFile.close();

写入

RandomAccessFile toFile = new RandomAccessFile("toFile1.txt", "rw");
FileChannel Channel = toFile.getChannel();

String newData = "something...";

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();

while(buf.hasRemaining()) {
    channel.write(buf);
}
Channel.close();
toFile.close();

注意 FileChannel用完后也要close

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值