JAVA IO流
1、 文件类(File)
文件:分为文件夹(目录)、普通文件(eg: .txt、 .avi、 .mp4、 .docx等)
Java中万事万物皆对象,系统中的各个文件也是一个对象(实例),既然是一个对象,那么就有类型,文件对象的类型就是File类型的。
Class File{
属性: 文件名、路径、数据大小等
方法: 创建、删除、修改(重命名,不能修改文件内部的内容)、查看等
}
File类的对象表示的是一个具体的文件(目录、普通文件)
package cn.java.file;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
public class FileTest {
@Test //junit工具包中的注解
public void createFile() throws IOException {
for (int i = 0; i < 5; i++) {
// java.txt就是一个具体的对象,这个对象使用File类型来表示
File file = new File(“C:\java” + i + “.txt”);
// 创建普通文件
boolean flag = file.createNewFile();
System.out.println(“file.createNewFile()=” + flag);
}
}
/*
* Description:创建文件夹
*/
@Test
public void createDirectory() throws IOException {
// java.txt就是一个具体的对象,这个对象使用File类型来表示
File file = new File(“C:\java.txt”);
file.mkdir();
}
@Test
public void test() throws IOException {
File file = new File(“c:\java0.txt”);
// 判断一个文件中是否有数据 ,len为0表示无数据,英文字母占1个字节,一个中文字占2字节
long len = file.length();
System.out.println(“len=” + len);
boolean flag = file.isFile();
System.out.println(“flag=” + flag);
}
}
2、java IO流
常见的取水的办法是我们用一根管道插到桶上面,然后在管道的另一边打开水龙头,桶里面的水就开始哗啦哗啦地从水龙头里流出来了,桶里面的水是通过这根管道流出来的,因此这根管道就叫流,JAVA里面的流式输入/输出跟水流的原理一模一样,当你要从文件读取数据的时候,一根管道插到文件里面去,然后文件里面的数据就顺着管道流出来,这时你在管道的另一头就可以读取到从文件流出来的各种各样的数据了。当你要往文件写入数据时,也是通过一根管道,让要写入的数据通过这根管道哗啦哗啦地流进文件里面去。除了从文件去取数据以外,还可以通过网络,比如用一根管道把我和你的机子连接起来,我说一句话,通过这个管道流进你的机子里面,你马上就可以看得到,而你说一句话,通过这根管道流到我的机子里面,我也马上就可以看到。
有的时候,一根管道不够用,比方说这根管道流过来的水有一些杂质,我们就可以在这个根管道的外面再包一层管道,把杂质给过滤掉。从程序的角度来讲,程序从计算机读取到的原始数据肯定都是010101这种形式的(二进制),一个字节一个字节地往外读
。
把输入设备或输出设备抽象为一各“水管”,水管中的每个“水滴”依次排序。每个“水滴”是最小的输入/输出单位,对于字节流而言,每个“水滴”是一个字节;对于字符流而言,每个“水滴”是一个字符。
3、字节流
字节流可以用于处理声音、视频、图片、文本等文件
一个字节占8位,字节流是对二进制序列按一个字节(8位)处理
无参read()在能读到字节的时候返回字节的ASCII码,不能读到的时候返回-1,这也是无参read不返回char的一个原因。带参的read返回的是读到的字节数。
package cn.java.file;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import org.junit.Test;
public class IoTest {
/*
* Description: 将程序代码中的数据保存到文件中去
*/
@Test
public void write2File() throws Exception {
Scanner input = new Scanner(System.in);
// 将文件封装成File对象
File file = new File(“c:\dt60.txt”);
System.out.print(“请录入数据:”);
String str = input.next();// 字节输出流
// 1、铺管道
FileOutputStream fos = new FileOutputStream(file, true);
// 2、打开水龙头,将java中的数据保存到磁盘中
fos.write(str.getBytes());
// 3、关闭水龙头
fos.close();
}
/*
* Description: 将磁盘上保存的数据读取到java代码中<br/>
*/
@Test
public void read2Java() throws Exception {// 中文乱码
// 将文件封装成File对象
File file = new File("c:\\dt60.txt");
// 1、建立磁盘通往程序代码的管道(字节输入流)
FileInputStream fis = new FileInputStream(file);
// 2、打开水龙头,读取数据
int len = 0;
while ((len = fis.read()) != -1) {
System.out.print((char) len);
}
// 3、关闭水龙头
fis.close();
}
// ------------------------------------(拷贝视频)------------------------------------------
@Test
public void copyVideo() throws Exception {// 免费
// 1、键c盘通往java代码的管道
FileInputStream fis = new FileInputStream("c:\\java.avi");
FileOutputStream fos = new FileOutputStream("d:\\java.avi");
int len = 0;
while ((len = fis.read()) != -1) {
// System.out.print((char) len);
// 2、将数据保存到D盘
fos.write(len);
}
fis.close();
fos.close();
}
@Test
public void copyVideoVip() throws Exception {// 收费版本
// 1、键c盘通往java代码的管道
FileInputStream fis = new FileInputStream("c:\\java.avi");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("d:\\java.avi");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] car = new byte[1024];// 1024个字节
int len = 0;// len=-1代表已经办完
while ((len = bis.read(car)) != -1) {
// 2.将读取的数据保存到D盘
// bos.write(car, 0, len);
System.out.println(new String(car, 0, len));
}
// 3、关闭输入流
bis.close();
fis.close();
// 关闭输出流
bos.close();
fos.close();
}
}
4、序列化
所谓的序列化就是将对象流化,就是将对象以一连串字节描述。
如何实现序列化呢?让某一个类实现Serializable接口(标记性接口,没有任何方法)
通俗的理解:比如对象类似于砖头,无法塞入到管道中传送给接收端,需要将砖头变成沙才能流动。序列化就是将砖头变成沙。Serializable接口就是标记
类可以被序列化。
package cn.java.io;
import java.io.Serializable;
public class Student implements Serializable {// 标记性接口
/**
* serialVersionUID:(用一句话描述这个变量表示什么).
*/
private static final long serialVersionUID = -9053011005074479085L;
private String stuNo;// 学号
private String stuName;// 学生的名字
private String gender;// 性别(男、女)
private Float height;// 身高
private Float weight;// 体重
public Student() {
super();
// Auto-generated constructor stub
}
public Student(String stuNo, String stuName, String gender, Float height, Float weight) {
super();
this.stuNo = stuNo;
this.stuName = stuName;
this.gender = gender;
this.height = height;
this.weight = weight;
}
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Float getHeight() {
return height;
}
public void setHeight(Float height) {
this.height = height;
}
public Float getWeight() {
return weight;
}
public void setWeight(Float weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", gender=" + gender + ", height=" + height
+ ", weight=" + weight + "]";
}
}
package cn.java.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import org.junit.Test;
public class IoTest {
// Description: 将某一个对象保存到文件中
@Test
public void object2File() throws Exception {
// 1、创建一个对象输出流
FileOutputStream fileOutputStream = new FileOutputStream(“c:\dt60.txt”);
ObjectOutputStream oos = new ObjectOutputStream(fileOutputStream);
Student student1 = new Student(“911”, “王二麻子”, “男”, 185.5F, 60F);
// 2、将对象写出
oos.writeObject(student1);
// 3、关闭流
oos.close();
fileOutputStream.close();
}
/*
* Description: 从文件中读取一个对象
*/
@Test
public void readFromFile() throws Exception {
FileInputStream fileInputStream = new FileInputStream(“c:\dt60.txt”);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
Student student = (Student) objectInputStream.readObject();
System.out.println(student);
objectInputStream.close();
fileInputStream.close();
}
}
5、字符流
字符
Java用char类型来表示字母、数字、标点符号以及其他特殊字符。Java基于Unicode4.0来表示每一个字符,Unicode的设计目标是容纳世界上所有主要语言中的字符。
Java使用16位即2个字节来表示字符,这意味着Java可以表示216,即65536个字符,看起来很多,但是还不能支持整个Unicode标准中的所有字符。如果超过这个范围,Java允许使用int类型来表示字符,int类型字长4个字节32位,可以表示232位的字符。
Java中表示字符的最简单的方式如下,使用单引号嵌入字符:
char capitalA = ‘A’;
字符从本质上讲是数字。每一个字符映射到一个范围在0到65 535的正整数,每一个字符在Unicode标准中都有对应的数字值,称为Unicode值。我们可以用如下方法来查看字符的Unicode码:
char word = ‘A’;
int p = 65;
System.out.println(“a在unicode表中的顺序位置是:” + (int) word);
System.out.println(“unicode表中的第65位是:” + (char) p);
字符流只能处理纯文本文件
package cn.java.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStreamWriter;
import org.junit.Test;
public class IoTest {
// -------------------------------------字符流----------------------------------------------
/**
* 字符输入流
*
* @throws FileNotFoundException
*/
@Test
public void readFile() throws Exception {
// 1、建立字符输入流
// FileInputStream---->BufferdInputStream
FileReader reader = new FileReader("c:\\Student.java");
// 2、打开水龙头
char[] car = new char[1024];
int len = 0;
while ((len = reader.read(car)) != -1) {
System.out.println(new String(car, 0, len));
}
// 3、关闭流
reader.close();
}
/*
* Description: 缓冲输入字符流<br/>
*/
@Test
public void readFile2() throws Exception {
// 1、建立字符输入流
// FileInputStream---->BufferdInputStream
FileReader reader = new FileReader("c:\\Student.java");
BufferedReader bReader = new BufferedReader(reader);
// 2、打开水龙头
String line = null;
while ((line = bReader.readLine()) != null) {
System.out.println(line);
}
// 3、关闭流
bReader.close();
reader.close();
}
/*
* Description: 通过字符输出流将数据保存到文件中<br/>
*/
@Test
public void write2File() throws Exception {
FileWriter fileWriter = new FileWriter("c:\\dt60.java", true);
fileWriter.write("Java从入门到放弃-价格:16800-作者:陈冠男");
// fileWriter.write("数据库从删库到跑路-价格:16800-作者:陈冠男");
fileWriter.close();
}
/*
* Description: 缓冲字符输出流<br/>
*/
@Test
public void write2File2() throws Exception {
FileWriter fileWriter = new FileWriter("c:\\dt60.java", true);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("Mybatis-一只smallbird");
bufferedWriter.newLine();// 通用的换行,各系统通用的换行方式
bufferedWriter.write("MybatisPlus-一只bigbird");
bufferedWriter.close();
fileWriter.close();
}
}
相同的数据,在不同的编码方式下得到的是不同的二进制序列。在磁盘上保存的数据实际上上二进制序列。使用编辑器打开文件时,使用相应的编码方式解码,才不会出现乱码。
相同的字符数据(unicode码元),不同的编码方式,有不同的二进制表示:
输出流:把要写入文件的字符序列(Unicode码元序列)转换为指定编码方式下的二进制序列,写入文件
输入流:把要读取的2个字节一个单元的字节序列按指定编码方式解码为相应的字符序列,存入内存。(为什么会选取两个字节,是由字符流决定的)
6、 字节流和字符流的区别
1、字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串
而字节流处理单元为 1 个字节,操作字节和字节数组
2、字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的
而字符流在操作的时候是使用到缓冲区的
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,
但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容。