Java中IO流讲解(一)
一、概念
- IO流用来处理设备之间的数据传输
- Java对数据的操作是通过流的方式
- Java用于操作流的类都在IO包中
- 流按流向分为两种:输入流,输出流
- 流按操作类型分为两种:
- 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
- 字符流 : 字符流只能操作纯字符数据,比较方便。
二、字节流
字节流的抽象父类:InputStream和OutputStream,由于抽象类是不能直接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 个字节写入此文件输出流。 |
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流讲解(一)的更多相关文章
- Java中IO流的总结
有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...
- java 中 IO 流分为几种?(未完成)
java 中 IO 流分为几种?(未完成)
- JAVA中IO流总结
本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42119261 我想你对JAVA的IO流有所了解,平时使用的 ...
- Java中IO流,输入输出流概述与总结
总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入 ...
- java中IO流相关知识点
(一) 下边使用outputStream字节输出流进行写操作 package zdbIO;import java.io.File;import java.io.FileNotFoundExceptio ...
- Java中IO流
* IO流用来处理设备之间的数据传输 * Java对数据的操作是通过流的方式 * Java用于操作流的类都在IO包中 * 流按流向分为两种:输入流,输出流. * 流按操作类型分为两种: * 字节流 : ...
- java中io流浅析
1.java.io包下File类:java程序中的此类的一个对象,就对应着硬盘中的一个文件或网络中的一个资源.File file1 = new File("d:\\io\\helloworl ...
- Java中IO流中的装饰设计模式(BufferReader的原理)
本文粗略的介绍下JavaIO的整体框架,重在解释BufferReader/BufferWriter的演变过程和原理(对应的设计模式) 一.JavaIO的简介 流按操作数据分为两种:字节流与字符流. 流 ...
- JAVA中IO流详解
IO流:数据传输是需要通道的,而IO流就是数据传输的通道. IO流可以形象的比喻为运送货物的传输带. IO流的分类: ①根据操作的数据类型的不同可以分为 :字节流与字符流. ②根据数据的流向分为:输入 ...
随机推荐
- CATIA 各个版本代号详解
一. 第几代(V-"version")简介 1982—1988年,catia相继发布了第一代—V1版本.第二代—V2版本.第三代—V3版本,并于1993年发布了功能强大的第四代—V ...
- python入门之集合set
集合(无序不重复) 创建 s = {} s = set() 转换 s = set(li) 方法 s.add("chy") #添加元素 s.clear() #清除元素 a = s.d ...
- 关于JavaDate数据返回到前端变数字的问题(并引申到前后端时间的传输)
不知道为什么,前端显示的所有数据项都没有错,就只有时间那一项很奇怪,是一串数字,而且这个数字在数据库怎么都找不到…… 然后我在后端从service到controller都debug了一遍,发现数据都没 ...
- C语言的面向对象技术
引言:面向过程的C有效率高,代码紧凑的特点,在单片机嵌入式领域是C的主要阵地,while(1)+中断是其主要的开发模式,但是当系统复杂到一定程度,想要添加一个功能需要改动很多地方,耦合性太强:跟别人交 ...
- [github][https模式下提交记住密码]
git版本 1.7.9以后 1. 开启 git config --global credential.helper cache 2. 设置时间 git config credential.helpe ...
- bootstrap-table 基础用法
1.需要添加的引用. <script src="@Url.Content("~/js/jquery-2.1.1.js")"></script& ...
- Vue实例的4个常用选项
1.过滤器 filters:在不改变的data的情况下输出前端页面需要的格式数据.例如将小数过滤为整数等.filters是一个对象,里边定义一个function方法,function传入一个参数,fu ...
- sqlserver 视图用 case when
视图用 case when 需要 用如下格式,[需要的列名]= case when...,而表里面的case 不用这样 [isNormal]=CASE WHENdbo.c_bdm_head.I_E_F ...
- Caused by: java.lang.NoClassDefFoundError: com/sun/tools/javac/util/List at
折腾了一下的时间,都没有找到解决的方案,在网上搜了一下答案都是让清理编译环境和重新打包之类的.就这样折腾一下,还没有解决问题.之所以会抛出找不到类的问题,需要排查你使用这个包的类是否存在,存在之后 查 ...
- 纪念一下我的第一个php扩展
C扩展代码 生成 so扩展文件( 很多文章介绍 生成so时候 喜欢用 # phpize ./configure ...... 刚开始掉进坑里面出不来 就是因为把这两个命令看成了一个 phpize ./ ...