一、概念

  • IO流用来处理设备之间的数据传输
  • Java对数据的操作是通过流的方式
  • Java用于操作流的类都在IO包中
  • 流按流向分为两种:输入流,输出流
  • 流按操作类型分为两种:
  1. 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
  2. 字符流 : 字符流只能操作纯字符数据,比较方便。

二、字节流

字节流的抽象父类InputStreamOutputStream,由于抽象类是不能直接new对象的,所以我们可以使用它们的子类来创建对象,下面我们主要来学习对文件的操作。FileInputStream对应文件输入流,FileOutputStream对应文件输出流。

1、FileInputStream常用方法介绍:

构造方法

FileInputStream(String name)   传入的参数为一个有效的文件路径,创建文件输入流对象

FileInputStream(File file)           传入的参数为一个文件对象,创建文件

成员方法

public int available()  throws IOException   返回剩余可读的字节数

public void close()  throws IOException      关闭流对象

public int read()  throws IOException           读取一个字节,返回值为读取到的字节的int类型值,读取到文件末尾返回-1

public int read(byte[] b)  throws IOException   最多读取b.length 个字节到字节数组b,返回读取到的字节数,读取到文件末尾返回-1

2、从文件上读取一个字节 read()

a.txt内容如下:
ab
import java.io.FileInputStream;
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
int x = fis.read(); //从硬盘上读取一个字节
System.out.println("x = " + x);
int y = fis.read();
System.out.println("y = " + y);
int z = fis.read();
System.out.println("z = " + z);
fis.close(); //关闭流
}
}
输出:
x = 97
y = 98
z = -1

read()方法一次读取一个字节,并把读取到的字节赋值成int类型,a对应的ascii码为97,b对应的为98,当读到文件末尾的时候,方法返回-1。有了上面的代码学习,我们可以对代码进行改进一下:

import java.io.FileInputStream;
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
int a;
while((a = fis.read()) != -1) {
System.out.println(a);
}
fis.close();
}
}
输出:
97
98

3、文件内容读取到字节数组 read(byte[] b)

a.txt内容如下:
abc
import java.io.FileInputStream;
public class FileInputStreamTest {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
byte[] arr = new byte[2]; //定义长度2的字节数组
int a = fis.read(arr); //一次最多将arr.length个字节读取到arr中,返回读取到的字节数
System.out.println("读取到的字节个数:" + a);
for (byte b : arr) {
System.out.println(b);
}
System.out.println("-----------");
a = fis.read(arr);
System.out.println("读取到的字节个数:" + a);
for (byte b : arr) {
System.out.println(b);
}
fis.close();
}
}
输出:读取到的字节个数:2
97
98
-----------
读取到的字节个数:1
99
98

第一次读取的时候,把a和b对应的97和98读取到arr,读取到的字节数是2,这个很好理解。看第二次的输出,第二次读取到1个字节也很好理解,因为a.txt的内容是abc,第一次ab都读过了,第二次就只读了剩下的c,但是字节数组输出是99和98。99对应的是c,但是怎么还会有个98(对应的是b)呢?这是因为在第一次读取的时候,97和98分别保存到了字节数组的0和1号索引。第二次读取到c的时候,用99覆盖了0号索引的97,而98还在1号索引。所以输出99和98

4、FileOutputStream常用方法介绍:

构造方法

FileOutputStream(File file)  创建向指定 File 对象表示的文件中写入数据的文件输出流

FileOutputStream(File file, boolean append)  和上面的方法的区别是,参数append如果是true表示在文件末尾追加。否则就覆盖

FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name, boolean append)  参数append的意思和FileOutputStream(File file, boolean append)一致

成员方法

public void close() throws IOException   关闭流对象

public void write(int b) throws IOException  将指定字节写入此文件输出流。

public void write(byte[] b) throws IOException  将 b.length 个字节从指定 byte 数组写入此文件输出流中

public void write(byte[] b, int off, int len) throws IOException 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

5、向文件写出一个字节 write(int b)
import java.io.FileOutputStream;
public class FileOutputStreamTest {
public static void main(String[] args) throws Exception {
// 如果没有就自动创建这个文件
FileOutputStream fos = new FileOutputStream("b.txt");
// 虽然写出的是int类型,但是写到文件的时候会自动去除前三个8位
fos.write(98);
fos.close();
}
}
文件b.txt的内容为:b

6、向文件写出字节数组的内容 write(byte[] b)

import java.io.FileOutputStream;
public class FileOutputStreamTest {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("b.txt");
byte[] arr = "hello,world!".getBytes();
fos.write(arr);
fos.close();
}
}
文件b.txt的内容为:hello,world!

三、文件内容拷贝

有了上面的学习后,我们就可以拷贝文件了。下面来看个例子,要求把a.txt的内容拷贝到b.txt

import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileCopyTest {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt");
byte[] arr = new byte[1024 * 8]; //定义字节数组的长度为8K
int len;
while((len = fis.read(arr)) != -1) { //len保存的是每次读取的字节数,保存到arr中
fos.write(arr, 0, len); //把arr的len个字节写出文件,0代表开始字节的索引位置
}
fis.close();
fos.close();
}
}

上面的这几行代码就是文件拷贝的核心代码,所有的其他文件拷贝方式都是在这几行代码的基础上进行的扩展。

四、字节流缓冲区

我们知道,如果一次读取一次字节,效率是非常慢的,所以我们想到了使用自定义字节数组,一次可以读取多个字节。但是我们都能想到,难道java的开发者难道想不到吗?所以就引入了两个字节流缓冲区类:

  • BufferedInputStream 字节输入流缓冲类
  • BufferOutputStream  字节输出流缓冲类

这个两个类的构造方法分别需要的参数类型是InputStream对象和OutputStream对象。它们都内置了大小为8192的字节的数组,我们先来看下如何使用,然后再具体分析,还是文件拷贝的例子:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BufferedTest {
public static void main(String[] args) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
int b;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
bos.close();
}
}

有的读者可能会产生这样的疑问,上面的代码不也是一个一个的读取的吗?凭什么它有优势,其实不然,在使用缓冲后,read的时候,是从文件上一次读取8192个字节,保存到输入流缓冲区数组,然后再一个字节一个字节的从输入流缓冲区把字节给java程序,write的时候,java程序再一个字节一个字节传给输出流缓冲区数组,等到输出流缓冲区数组存够8192个字节的时候,再一次性的写出文件上。不使用缓冲区的时候,read方法是一个字节一个字节的从文件读取传递给java程序,write的时候java程序再一个字节一个字节的把字节往文件写。一个字节一个字节的操作相当于是硬盘----java程序(内存)-----硬盘,使用缓冲区后,一个字节一个字节的操作相当于在两个字节流缓冲数组中进行的,输入流缓冲数组(内存)----java程序(内存)----输出流缓冲数组(内存)相当于是在内存中进行传递。我们知道,内存的操作速度是远远大于硬盘的,所以使用缓冲的效率更高。

那么使用缓存和我们自定义字节数组的效率哪个比较高呢?答案是自定义字节数组效率稍微高那么一点点,因为自定义字节数组我们操作是的一个字节数组,而缓冲是两个字节数组,这两个字节数组之间还需要传递字节,但是由于是在内存中进行字节传递,所以效率也是比较高的。这两种方法其实差别不大!

我们会在下篇博文继续讲解字符流的使用!

Java中IO流讲解(一)的更多相关文章

  1. Java中IO流的总结

    有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...

  2. java 中 IO 流分为几种?(未完成)

    java 中 IO 流分为几种?(未完成)

  3. JAVA中IO流总结

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42119261 我想你对JAVA的IO流有所了解,平时使用的 ...

  4. Java中IO流,输入输出流概述与总结

    总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入 ...

  5. java中IO流相关知识点

    (一) 下边使用outputStream字节输出流进行写操作 package zdbIO;import java.io.File;import java.io.FileNotFoundExceptio ...

  6. Java中IO流

    * IO流用来处理设备之间的数据传输 * Java对数据的操作是通过流的方式 * Java用于操作流的类都在IO包中 * 流按流向分为两种:输入流,输出流. * 流按操作类型分为两种: * 字节流 : ...

  7. java中io流浅析

    1.java.io包下File类:java程序中的此类的一个对象,就对应着硬盘中的一个文件或网络中的一个资源.File file1 = new File("d:\\io\\helloworl ...

  8. Java中IO流中的装饰设计模式(BufferReader的原理)

    本文粗略的介绍下JavaIO的整体框架,重在解释BufferReader/BufferWriter的演变过程和原理(对应的设计模式) 一.JavaIO的简介 流按操作数据分为两种:字节流与字符流. 流 ...

  9. JAVA中IO流详解

    IO流:数据传输是需要通道的,而IO流就是数据传输的通道. IO流可以形象的比喻为运送货物的传输带. IO流的分类: ①根据操作的数据类型的不同可以分为 :字节流与字符流. ②根据数据的流向分为:输入 ...

随机推荐

  1. 洛谷1941(dp)

    常规的dp,当前有值且碰不到管子就转移,可以连跳的操作我就加了一维表示当前是不是连跳过来的.第二问前缀和即可得(不对啊边走边记录就行了吧我冗了Orz). #include <cstdio> ...

  2. @Results( 中 params 怎么用

    http://blog.csdn.net/z69183787/article/details/16342553 struts2的@Result annotation 如何添加params,并且在页面取 ...

  3. 字符串与C51的格式化输出

    一字符数组和字符指针: 字符指针可以用字符串对其直接初始化和随时赋值:而字符数组可以用字符串进行初始化,但不能用字符串对其进行随时赋值(但此时可以定义一个字符串指针指向字符数组,然后用字符串对指针随时 ...

  4. ubuntu 文件解压命令

    [解压.zip文件] unzip ./FileName.zip //前提是安装了unzip 安装unzip命令:sudo apt-get install unzip 卸载unzip软件 命令:sudo ...

  5. java 利用c3p0管理数据库连接池

    数据库连接池类,用于获取数据库连接.利用单例模式保证所有的连接都只通过一个连接池管理. package com.mousewheel.dbcon; import java.io.InputStream ...

  6. ES6语言特性,如何在低版本浏览器运行它

    Introduction ECMAScript 6 于今年6月正式成为了标准,关于ES6,我们最大的疑虑可能是客户端浏览器还没有完全支持它,也就node.js用用. 有很多种手段可以解决这个问题,比如 ...

  7. vue从入门到开发--4--处理http请求

    一: 在main.js里面处理http请求模块,因为没有这个模块,所以需要先安装这个模块:npm install vue-resource --save 安装完毕之后,导入这个模块,并使用中间件将其使 ...

  8. [windows]桌面中添加我的电脑,我的文档和网上邻居图标

    xp系统: 操作步骤:桌面任意位置--〉右键--〉属性--〉桌面选项卡--〉自定义桌面--〉常规:勾选相关图标确定即可. win7系统: 操作步骤:桌面任意位置--〉右键--〉个性化--〉(右侧)更改 ...

  9. Javafinal变量

    class Test02 {     public static void main(String args[]){         final int x;         x = 100; //  ...

  10. 洛谷 P2264 情书

    题目背景 一封好的情书需要撰写人全身心的投入.lin_toto同学看上了可爱的卡速米想对她表白,但却不知道自己写的情书是否能感动她,现在他带着情书请你来帮助他. 题目描述 为了帮助lin_toto,我 ...