IO流学习笔记
IO流
参考:http://c.biancheng.net/java/130/;
流的概念
在 java 中所有数据都是使用流读写的。流是一组有序的数据序列,将数据从一个地方带到另一个地方
输入:是将数据从各种输入设备(包括文件、键盘等)中读取到内存中,
输出:是将数据写入到各种输出设备(比如文件、显示器、磁盘等)。
流的分类
数据流是 Java 进行 I/O 操作的对象,它按照不同的标准可以分为不同的类别。
按方向
- 输入流:将<存储设备>中的内容读到<内存>中
- 输出流:将<内存>中的内容写到<存储设备>中
按单位
- 字节流:以字节为单位,可以读写所有数据
- 字符流:以字符为单位,只能读写文本数据
按功能
- 节点流:具有实际传输数据的读写功能
- 处理流:在节点流的基础之上增强功能
输入流和输出流本身都是抽象类,不能直接实例化,如果想操作对象,则必须实例化这些类的子类对象.
输入流
Java 流相关的类都封装在 java.io 包中,而且每个数据流都是一个对象。所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。其中 InputStream 类是字节输入流的抽象类,是所有字节输入流的父类
输出流
在 Java 中所有输出流类都是 OutputStream 抽象类(字节输出流)和 Writer 抽象类(字符输出流)的子类。其中 OutputStream 类是字节输出流的抽象类,是所有字节输出流的父类,
系统流
每个java程序运行时都带有一个系统流,系统流对应的类为 java.lang.System。Sytem 类封装了 Java 程序运行时的 3 个系统流,分别通过 in、out 和 err 变量来引用。这 3 个系统流如下所示:
- System.in:标准输入流,默认设备是键盘。
- System.out:标准输出流,默认设备是控制台。
- System.err:标准错误流,默认设备是控制台。
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) {
byte[] byteData = new byte[100]; // 声明一个字节数组
System.out.println("请输入英文:");
try {
System.in.read(byteData);//读取
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("您输入的内容如下:");
for (int i = 0; i < byteData.length; i++) {
System.out.write((char) byteData[i]);//输出,强转为字符类型
}
}
}
System.in 是 InputStream 类的一个对象,因此上述代码的 System.in.read() 方法实际是访问 InputStream 类定义的 read() 方法。该方法可以从键盘读取一个或多个字符。对于 System.out 输出流主要用于将指定内容输出到控制台。
System.out 和 System.error 是 PrintStream 类的对象。因为 PrintStream 是一个从 OutputStream 派生的输出流,所以它还执行低级别的 write() 方法。因此,除了 print() 和 println() 方法可以完成控制台输出以外,System.out 还可以调用 write() 方法实现控制台输出。
该方法通过 byteval 参数向文件写入指定的字节。在实际操作中,print() 方法和 println() 方法比 write() 方法更常用。
注意:尽管它们通常用于对控制台进行读取和写入字符,但是这些都是字节流。因为预定义流是没有引入字符流的 Java 原始规范的一部分,所以它们不是字符流而是字节流,但是在 Java 中可以将它们打包到基于字符的流中使用。
字符编码介绍
Java 中常见编码说明如下:
- ISO8859-1:属于单字节编码,最多只能表示 0~255 的字符范围。
- GBK/GB2312:中文的国标编码,用来表示汉字,属于双字节编码。GBK 可以表示简体中文和繁体中文,而 GB2312 只能表示简体中文。GBK 兼容 GB2312。
- Unicode:是一种编码规范,是为解决全球字符通用编码而设计的。UTF-8 和 UTF-16 是这种规范的一种实现,此编码不兼容 ISO8859-1 编码。Java 内部采用此编码。
- UTF:UTF 编码兼容了 ISO8859-1 编码,同时也可以用来表示所有的语言字符,不过 UTF 编码是不定长编码,每一个字符的长度为 1~6 个字节不等。一般在中文网页中使用此编码,可以节省空间。
本地的默认编码可以使用 System 类查看。Java 中 System 类可以取得与系统有关的信息,所以直接使用此类可以找到系统的默认编码。方法如下所示:
public static Properties getProperty()
使用上述方法可以查看 JVM 的默认编码,代码如下:
public static void main(String[] args) {
// 获取当前系统编码
System.out.println("系统默认编码:" + System.getProperty("file.encoding"));
}
字节流的使用
字节输入流
InputStream 类及其子类的对象表示字节输入流,InputStream 类的常用子类如下。
- ByteArrayInputStream 类:将字节数组转换为字节输入流,从中读取字节。
- FileInputStream 类:从文件中读取数据。
- PipedInputStream 类:连接到一个 PipedOutputStream(管道输出流)。
- SequenceInputStream 类:将多个字节输入流串联成一个字节输入流。
- ObjectInputStream 类:将对象反序列化。
使用 InputStream 类的方法可以从流中读取一个或一批字节。下面 列出了 InputStream 类的常用方法。
方法名及返回值类型 | 说明 |
---|---|
int read() | 从输入流中读取一个 8 位的字节,并把它转换为 0~255 的整数,最后返回整数。 如果返回 -1,则表示已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量 使用 read() 方法的另外两种形式 |
int read(byte[] b) | 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。 该方法返回 读取的字节数。如果返回 -1,则表示已经到了输入流的末尾 |
int read(byte[] b, int off, int len) | 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。其中,off 指 定在字节数组中开始保存数据的起始下标;len 指定读取的字节数。该方法返回实际 读取的字节数。如果返回 -1,则表示已经到了输入流的末尾 |
void close() | 关闭输入流。在读操作完成后,应该关闭输入流,系统将会释放与这个输入流相关 的资源。注意,InputStream 类本身的 close() 方法不执行任何操作,但是它的许多 子类重写了 close() 方法 |
int available() | 返回可以从输入流中读取的字节数 |
long skip(long n) | 从输入流中跳过参数 n 指定数目的字节。该方法返回跳过的字节数 |
void mark(int readLimit) | 在输入流的当前位置开始设置标记,参数 readLimit 则指定了最多被设置标记的字 节数 |
boolean markSupported() | 判断当前输入流是否允许设置标记,是则返回 true,否则返回 false |
void reset() | 将输入流的指针返回到设置标记的起始处 |
注意:在使用 mark() 方法和 reset() 方法之前,需要判断该文件系统是否支持这两个方法,以避免对程序造成影响。
字节输出流
OutputStream 类及其子类的对象表示一个字节输出流。OutputStream 类的常用子类如下。
- ByteArrayOutputStream 类:向内存缓冲区的字节数组中写数据。
- FileOutputStream 类:向文件中写数据。
- PipedOutputStream 类:连接到一个 PipedlntputStream(管道输入流)。
- ObjectOutputStream 类:将对象序列化。
利用 OutputStream 类的方法可以从流中写入一个或一批字节。下面列出了 OutputStream 类的常用方法。
方法名及返回值类型 | 说明 |
---|---|
void write(int b) | 向输出流写入一个字节。这里的参数是 int 类型,但是它允许使用表达式, 而不用强制转换成 byte 类型。为了提高 I/O 操作的效率,建议尽量使用 write() 方法的另外两种形式 |
void write(byte[] b) | 把参数 b 指定的字节数组中的所有字节写到输出流中 |
void write(byte[] b,int off,int len) | 把参数 b 指定的字节数组中的若干字节写到输出流中。其中,off 指定字节 数组中的起始下标,len 表示元素个数 |
void close() | 关闭输出流。写操作完成后,应该关闭输出流。系统将会释放与这个输出 流相关的资源。注意,OutputStream 类本身的 close() 方法不执行任何操 作,但是它的许多子类重写了 close() 方法 |
void flush() | 为了提高效率,在向输出流中写入数据时,数据一般会先保存到内存缓冲 区中,只有当缓冲区中的数据达到一定程度时,缓冲区中的数据才会被写 入输出流中。使用 flush() 方法则可以强制将缓冲区中的数据写入输出流, 并清空缓冲区 |
文件字节流
文件字节输入流
在创建 FileInputStream 类的对象时,如果找不到指定的文件将拋出 FileNotFoundException 异常,该异常必须捕获或声明拋出。
import java.io.FileInputStream;
/**
* FileInputStream的使用
* 文件字节输入流,从文件中读取数据
*/
public class Demo03 {
public static void main(String[] args) throws Exception{
//1.创建FileInputStream,并指定文件路径
FileInputStream fis = new FileInputStream("F:\\file\\word.txt");
//2读取文件
// fis.read();
//1.单个字节读取输出
// int data = 0;
// //如果 = -1 则说明读完了 跳出循环
// while((data = fis.read())!= -1){
// System.out.println((char)data);
// }
//2.读出多个字节输出
byte [] buf = new byte[5]; // 周转的缓冲区
int len = 0;//读取的长度
while((len = fis.read(buf))!= -1){
System.out.println(new String(buf,0,len));
System.out.println(len);//读取的长度
}
fis.close();//关闭输入流
System.out.println("执行完毕");
}
}
文件字节输出流
import java.io.FileOutputStream;
/**
*FileOutputStream的使用
* 文件字节输出流,向文件中写入数据
*/
public class Demo04 {
public static void main(String[] args) throws Exception{
//创建FileOutputStream对象,没文件会自动创建
//每次执行都会把原为文件内容覆盖
FileOutputStream fos = new FileOutputStream("F:\\file\\word.txt");
//不会覆盖原来的内容
// FileOutputStream fos = new FileOutputStream("F:\\file\\word.txt",true);
fos.write(97); //写入的是unicode码对应的字符
fos.write('b');
fos.write('c');
byte[] buf = {'d','c','s','s','g'};//定义一个字节数组
fos.write(buf);
String string = "hello world";
fos.write(string.getBytes());//string转为一个字节数组
//强制将缓冲区中的数据写入输出流,
//并清空缓冲区
fos.flush();
fos.close();
System.out.println("执行完毕");
}
}
字节流复制文件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 复制文件
*/
public class Demo05 {
public static void main(String[] args) {
//创建文件字节输入流
File file = new File("F:\\file\\word.txt");
FileInputStream fis = null;
//创建文件字节输出流
FileOutputStream fos = null;
try{
fis = new FileInputStream(file);
//文件不存在会自动创建
fos = new FileOutputStream("F:\\file\\word1.txt");
byte[] buf = new byte[1024];//周转的缓存区
int len = 0; //读取的字节长度
//边读边写
while((len = fis.read(buf)) != -1){
fos.write(buf,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
fis.close();//关闭输入流
fos.close();//关闭输出流
}catch (Exception e){
e.printStackTrace();
}
}
System.out.println("执行完毕");
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* 图片复制
*/
public class Demo06 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("F:\\file\\01.jpg");
FileOutputStream fos = new FileOutputStream("F:\\file\\02.jpg");
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf))!= -1){
fos.write(buf);
}
fis.close();
fos.close();
System.out.println("执行完毕");
}
}
字节缓冲流
- 缓冲流 BufferInputStream/BufferOutputStream
- 提高I0效率,减少访问磁盘的次数;
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。
字节输入缓冲流
import java.io.BufferedInputStream;
import java.io.FileInputStream;
/**
* 使用字节缓冲流
* BufferInputStream
*/
public class Demo07 {
public static void main(String[] args) throws Exception{
//BufferInputStream实例化
FileInputStream fis = new FileInputStream("F:\\file\\word.txt");
BufferedInputStream bis = new BufferedInputStream(fis); //提高读的速率
//读数据
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf)) != -1){
System.out.println(new String(buf,0,len));
}
bis.close();//会自动把fis关闭
}
}
字节输出缓冲流
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
/**
* 字节输出缓冲流的使用
* BufferOutputStream
*/
public class Demo08 {
public static void main(String[] args) throws Exception{
//BufferedOutputStream实例化
FileOutputStream fos = new FileOutputStream("F:\\file\\buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("hello world".getBytes());//写入到BufferedOutputStream维护的缓冲区
//强制将缓冲区中的数据写入输出流,
//并清空缓冲区
bos.flush();
//close()方法里面调用了flush()方法,可以省略flush()不写
bos.close();
System.out.println("执行完毕");
}
}
对象流
-
对象流: Object0utputStream / 0bjectInputStream
- 增强了缓冲区功能
- 增强了读写8种基本数据类型和字符串功能
- 增强了读写对象的功能:
- readd0bject() 从流中读取一个对象
- write0bject (0bject obj) 向流中写入一一个对象
使用流传输对象的过程称为序列化、反序列化。
ObjectInputStream 类:将对象反序列化。
ObjectOutputStream 类:将对象序列化。
序列化(ObjectOutputStream)
注意:序列化的类 需要实现Serializable接口
* 序列化类中的对象属性也需要 实现Serializable接口
* 序列化版本号ID,保证序列化的类和反序列化的类是同一个类
* 使用transient(瞬间的)修饰属性,这个属性不能序列化
* 静态属性不能序列化
* 序列化多个对象,可以借助集合来实现
import java.io.Serializable;
/**
* 该类想要序列化,需要实现Serializable接口,否则不能序列化
*/
public class Student implements Serializable {
//serialVersionUID 序列化版本号ID
private final static long serialVersionUID= 1L;
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* 使用ObjectOutputStream实现对象的序列化
* 注意:序列化的类 需要实现Serializable接口
* 序列化类中的对象属性也需要 实现Serializable接口
* 序列化版本号ID,保证序列化的类和反序列化的类是同一个类
* 使用transient(瞬间的)修饰属性,这个属性不能序列化
* 静态属性不能序列化
* 序列化多个对象,可以借助集合来实现
*
*/
public class Demo09 {
public static void main(String[] args) throws Exception{
//实例化ObjectOutputStream
FileOutputStream fos = new FileOutputStream("F:\\file\\Object.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//序列化写入操作
Student student = new Student("张三",20);
Student student1 = new Student("李四",21);
//1.
// oos.writeObject(student);
// oos.writeObject(student1);
//2.使用集合
List<Student> students = new ArrayList<>();
students.add(student);
students.add(student1);
oos.writeObject(students);
oos.close();
System.out.println("执行完毕");
}
}
文件会乱码
反序列化(ObjectInputStream)
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;
/**
* 使用ObjectInputStream实现反序列化(读取重构成对象)
*/
public class Demo10 {
public static void main(String[] args) throws Exception{
// 创建对象流
FileInputStream fis = new FileInputStream("F:\\file\\Object.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
//读取文件(反序列化)
//1.
// Student student =(Student) ois.readObject();
// Student student1 = (Student) ois.readObject();
// System.out.println(student.toString());
// System.out.println(student1.toString());
//2.
List<Student> students =(List<Student>) ois.readObject();
System.out.println(students.toString());
//关闭
ois.close();
System.out.println("执行完毕");
}
}
待加…
本文地址:https://blog.csdn.net/qian4517/article/details/109817369
上一篇: 报告称Apple Pay用户增长放缓