Java IO流初步
一、Java IO流简介
I 为Input,O 为Output 。
在Java程序中,对于数据的输入、输出操作以 流(stream)方式进行。从外部的存储媒介或其他程序中读入所需的数据时需要使用 输入流。而程序在处理数据后,可能需要将处理的结果写入到永久的存储媒介中或传送给其他应用程序,这时便需要使用 输出流。输入流的指向称为 源,输出流的指向称为它的 目的地,“源”和“目的地”经常为磁盘文件,也可以为键盘,内存或显示器窗口。
二、Java流类的分类
Java.iO包中提供了大量的流类,用以获取不同种类的数据,可以从不同的角度对其进行分类:
- 按数据流的方向不同可以分为输入流和输出流。
- 按处理数据单位不同可以分为字节流和字符流。
字节流与字符流的区别:
- 读取单位不同,字节流的读取单位为1 byte = 8 bit,而字符流的读取单位为1 char = 2 byte = 16 bit。
- 适用场景不同,字节流可以处理任意类型的数据,如图片、视频等;而字符流只能读取纯文本文件。
- 字节流默认不使用缓冲,而字符流会使用缓冲。
- 按照功能不同可以分为节点流和处理流。
节点流与处理流的区别:
- 节点流直接从一个特定的数据源(节点)读写数据。
- 处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
所有的输入流都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类,所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
常用方法:
int read() throws IOException /* 读取一个字节并以整数的形式返回
(0 ~ 255),若已到输入流的末尾则返回-1 */
int read(byte[] buffer) throws IOException /*读取一系列字节并存储到一
个数组buffer,返回实际读取的字节数,如果读取前已到输入流的末尾返回-1 */
int read(byte[] buffer, int offset, int len) throws IOException
/* 读取len个字节,并从offset位置开始,存储到一个字节数组buffer,
返回实际读取的字节数,如果读取前已到输入流的末尾返回-1 */
void close() throws IOException // 关闭流释放内存资源
long skip(long n) throws IOException /* 跳过n个字节不读,返回实际跳过
的字节数 */
void write(int n) throws IOException /* 向输出流中写入一个字节数据,
该字节数据为参数n的低8位 */
void wirte(byte[] n) throws IOException /* 将一个字节类型的数组中的
数据写入输出流 */
void write(byte[] n, int offset, int len) throws IOException /* 将
一个字节类型的数组中从offset位置开始的len个字节写入到输出流中 */
void close() throws IOException // 关闭流释放资源
void flush() throws IOException //将输出流中缓冲的数据全部写出到目的地
int read() throws IOException /* 读取一个字符并以整数的形式返回
(0 ~ 255),若已到输入流的末尾则返回-1 */
int read(char[] cbuf) throws IOException /*读取一系列字符并存储到一个
数组buffer,返回实际读取的字符数,如果读取前已到输入流的末尾返回-1 */
int read(char[] cbuf, int offset, int len) throws IOException /*
读取len个字符,并从offset位置开始,存储到一个数组buffer,返回实际读取的
字符数,如果读取前已到输入流的末尾返回-1 */
void close() throws IOException // 关闭流释放内存资源
void skip(long n) throws IOException /* 跳过n个字符不读,返回实际跳过
的字符数 */
void write(int n) throws IOException /* 向输出流中写入一个字符数据,
该字符数据为参数n的低16位 */
void write(char[] cbuf) throws IOException /*将一个字符类型的数组写入
中的数据写入输出流 */
void write(char[] cbuf, int offset, int len) throws IOException
/* 将一个字符类型的数组中从offset位置开始的len个字符写入到输出流中 */
void write(String str) throws IOException /* 将一个字符串中的字符写入
到输出流中 */
void write(String str, int offset, int len) throws IOException
/* 将一个字符串中从offset位置开始的len个字符写入到输出流中 */
void close() throws IOException // 关闭流释放内存资源
void flush() throws IOException //将输出流中缓冲的数据全部写出到目的地
三、Java常用节点流和处理流
节点流:
1、文件流:
了解文件流之前需要先了解文件(File)类
File类:
File类的对象主要用于获取文件本身的一些信息,不涉及对文件的读写操作。
创建一个File对象的构造方法有3个:
File(String filename) // filename 为文件名字
File(String directoryPath, String filename) // directory 为文件的路径
File(File dir, String filename) // dir 为一个目录
File类中的常用方法:
public String getName() // 获取文件的名字
public boolean exists() // 判断文件是否存在
public long length() // 获取文件的长度(单位为字节)
public String getAbsolutePath() // 获取文件的绝对路径
public String getParent() // 获取文件的父目录
public boolean file.mkdir() /* 创建一个目录,如果创建成功,返回true,
创建失败,返回false。如果这个文件夹已经存在,则返回false */
public boolean file.mkdirs() /* 创建多级目录,成功返回true,失败则
返回 false */
public boolean file.createNewFile() /* 创建一个新文件,创建成功,
返回true;创建失败,返回false。如果这个文件已经存在,则返回false */
public String[] list() // 以字符串形式返回目录下的全部文件
public File [] listFiles() // 以File对象的形式返回目录下的全部文件
简单写一个小程序测试一下:
import java.io.File;
public class test {
public static void main(String[] args) {
File f_1 = new File("D:\\java", "HW.txt");
System.out.println("文件是否存在:" + f_1.exists());
System.out.println("文件的名字为:" + f_1.getName());
System.out.println("文件的长度为:" + f_1.length());
System.out.println("文件的绝对路径为: " + f_1.getAbsolutePath());
File f_2 = new File("D:\\java");
String list[] = f_2.list();
System.out.println("该目录下的文件有:");
for (String string : list){
System.out.println(string);
}
}
}
/*
文件是否存在:true
文件的名字为:HW.txt
文件的长度为:14
文件的绝对路径为: D:\java\HW.txt
该目录下的文件有:
.metadata
apache-tomcat-8.5.77
HW.txt
IntelliJ IDEA 2021.3.3
Navicat Premium 15
text
*/
FileInputStream类(文件字节输入流)
1、构造方法
FileInputStream(String name); // 使用给定的文件名创建
FileInputStream(File file); // 使用File对象创建
2、代码演示
读取一个写有“Hello World”的txt文件:
import java.io.*;
public class test {
public static void main(String[] args) {
int n = -1;
FileInputStream in = null;
try {
in = new FileInputStream("D:\\java\\HW.txt");
} catch (FileNotFoundException e) {
System.out.println("找不到指定文件");
System.exit(-1);
}
try {
while ((n = in.read()) != -1) {
System.out.print((char) n);
}
in.close();
} catch (IOException e1) {
System.out.println("文件读取错误");
System.exit(-1);
}
}
}
/*
输出结果:
Hello,World
*/
FileOutputStream类(文件字节输出流)
1、构造方法
FileOutputStream(String name); // 使用给定的文件名创建
FileOutputStream(File file); // 使用File对象创建
2、代码演示
import java.io.*;
public class test {
public static void main(String[] args) {
int n = -1;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("D:\\java\\HW.txt");
out = new FileOutputStream("D:\\java\\HW2.txt"); /* 若没
有该文件,则系统会自动创建一个。*/
while((n = in.read())!= -1){
out.write(n);
}
in.close();
out.close();
}
catch (FileNotFoundException e1) {
System.out.println("未找到指定文件");
System.exit(-1);
}catch (IOException e2){
System.out.println("文件复制错误");
System.exit(-1);
}
System.out.println("文件复制成功,内容为:");
// 读取 HW2.txt 文件
FileInputStream _in = null;
int m = -1;
try {
_in = new FileInputStream("D:\\java\\HW2.txt");
} catch (FileNotFoundException e) {
System.out.println("找不到指定文件");
System.exit(-1);
}
try {
while ((m = _in.read()) != -1) {
System.out.print((char) m);
}
_in.close();
} catch (IOException e3) {
System.out.println("文件读取错误");
System.exit(-1);
}
}
}
/*
输出结果为:
文件复制成功,内容为:
Hellow,World
*/
FileReader类与FileWriter类(文件字符输入、输出流)
1、构造方法
FileReader(String filename);
FileReader(File filename);
FileWriter(String filename);
FileWriter(File filename)
FileWriter(String filename, boolean append)
FileWriter(File filename, boolean append)
2、代码演示
将写有“你好,World”的HW.txt文件复制给HW2.txt文件
import java.io.*;
public class test {
public static void main(String[] args) {
int n = -1;
File reader = new File("D:\\java\\HW.txt");
File write = new File("D:\\java\\HW2.txt");
char s[] = new char[20];
try {
Writer out = new FileWriter(write, true);
Reader in = new FileReader(reader);
while ((n = in.read(s)) != -1) {
out.write(s, 0, n);
}
out.flush();
out.close();
} catch (IOException e) {
System.out.println("文件读取错误");
System.exit(-1);
}
System.out.println("文件复制成功");
}
}
/*
输出结果为:
文件复制成功
*/
处理流:
1、缓冲流:
BufferedInputStream类与BufferedOutputStream类:
缓冲输入、输出流 相较字符输入流和字符输出流有更强的读写能力,如BufferedReader流就可以使用方法readLine()按行读取文件。
构造方法
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)
// size为自定义缓存区的大小
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int size)
代码示例
HW.txt中写有英文字母表A-Z。
import java.io.*;
public class test {
public static void main(String[] args) {
try {
int n = 0;
int i = 0;
//创建一个FileInputStream流
FileInputStream f = new FileInputStream("D:\\java\\HW.txt");
//再创建一个BufferedInputStrea流,并将它与FileInputStream流连接在一起
BufferedInputStream buf = new BufferedInputStream(f);
for (i = 0; i < 5 && (n = buf.read())!= -1;i++){
System.out.println((char) n);
}
buf.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
/*
输出结果为:
A
B
C
D
E
*/
BufferedReader类与BufferedWriter类:
构造方法
BufferedReader(Reader in)
BufferedReader(Reader in, int size)
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)
代码示例
HW.txt中的字符为:
ABCDEFGHIJKLMN
OPQRST
UVWX
YZ
HW2.txt为空
import java.io.*;
public class test {
public static void main(String[] args) {
try {
FileReader r = new FileReader("D:\\java\\HW.txt");
FileWriter w = new FileWriter("D:\\java\\HW2.txt");
BufferedReader br = new BufferedReader(r);
BufferedWriter bw = new BufferedWriter(w);
String s = br.readLine();
bw.write(s);
bw.flush();
while ((s = br.readLine()) != null) {
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*输出结果为:
OPQRST
UVWX
YZ
*/
/*
HW2.txt中的字符为:
ABCDEFGHIJKLMN
*/
2、数据流:
数据输入流和数据输出流允许程序按着机器无关的风格读取Java原始数据,即读取一个数值时,不必再关心这个数值应当是多少个字节。
DataInputStream类与DataOutputStream类:
构造方法
DataInputStream(InputStream in)
// 创造的数据输入流指向一个由参数in指定的底层输入流
DataOutputStream(OutputStream out)
// 创造的数据输出流指向一个由参数out指定的底层输出流
常用方法
字面意思便可理解的不多解释
close(); // 关闭流
readBoolean();
readByte();
readChar();
readDouble():
readFloat();
readInt();
readLong();
readShort();
readUnsignedByte(); // 读取一个无符号字节
readUTF(); // 读取一个UTF字符串
skipBytes(int n); // 跳过给定数量的字节
writeInt(int n);
writeBytes(String s);
writeBoolean(boolean n);
writeChars(String s);
writeDouble(double n);
writeFloat(float n);
writeLong(long n);
writeShort(int n);
writeUTF(String s);
代码示例
将几个数据写入到HW.txt文件再读出
import java.io.*;
public class test {
public static void main(String[] args) {
try {
FileOutputStream out = new FileOutputStream("D:\\JAVA\\HW.txt");
DataOutputStream outdata = new DataOutputStream(out);
outdata.writeBoolean(true);
outdata.writeFloat(3.14f);
outdata.writeChars("Lin");
} catch (IOException e1) {
System.exit(-1);
}
try {
FileInputStream in = new FileInputStream("D:\\JAVA\\HW.txt");
DataInputStream indate = new DataInputStream(in);
System.out.println(indate.readBoolean());
System.out.println(indate.readFloat());
char s = '\0';
while ((s = indate.readChar()) != '\0') {
System.out.print(s);
}
} catch (IOException e) {}
}
}
/*
输出结果为:
true
3.14
Lin
*/
3、转换流:
转换流 InputStreamReader 和 OutputStreamWriter 实现了字节流和字符流之间的转换。
InputStreamReader类与OutputStreamWriter类:
代码示例
import java.io.*;
public class test {
public static void main(String[] args) {
try {
FileOutputStream out = new FileOutputStream("D:\\java\\HW.txt");
OutputStreamWriter ow = new OutputStreamWriter(out);
ow.write("ABCD霖");
ow.close();
} catch (IOException e1) {
System.exit(-1);
}
try {
FileInputStream in = new FileInputStream("D:\\java\\HW.txt");
InputStreamReader is = new InputStreamReader(in);
int s = -1;
while ((s = is.read()) != -1) {
System.out.print((char) s);
}
} catch (IOException e2) {
System.exit(-1);
}
}
}
/*
输出结果为:
ABCD霖
*/