流就是指一连串流动的字符,以先进先出的方式发送信息的通道。
文件输入——读
文件输出——写
文件:可认为是相关记录或放在一起的数据的集合。
在Java中,使用java.io.File类对文件进行操作。
File类:

构造方法:

常用方法
是否可读或可写:canRead()和canWrite()

文件是否存在:exists()

获取文件或路径的名称:getName()

是否是目录或文件:isDirectory()和isFile()——若文件不存在,false

是否是隐藏文件:isHidden()

返回文件的最后一次修改时间:lastModified()

创建目录/创建多级目录:mkdir()/mkdirs()

我在C盘有一个文件夹temp,里面有一个txt文件名为score。
则它在Windows下的路径为:c:\\temp\\score.txt。(一个\是转义字符)
代码1:
isFile()和isDirectory()public class FileDemo {
public static void main(String[] args) {
// 创建File对象
File file = new File("c:\\temp\\score.txt");
// 判断是否文件or目录
boolean flag1 = file.isFile();
boolean flag2 = file.isDirectory();
System.out.println("是否是文件:" + flag1);
System.out.println("是否是目录:" + flag2);
}
}
输出:
是否是文件:true
是否是目录:false
也可以这样:
File file=new File("c:\\temp","score.txt");
或
File file1=new File("c:\\temp");
File file=new File(file1,"score.txt");
代码2:
exists():判断文件是否存在mkdir():创建文件目录// 创建一个目录
File file2 = new File("c:\\temp", "HashSet");
// 判断这个文件是否存在
if (!file2.exists()) {
file2.mkdir();
}
运行后:

如果想创建多级目录:(先把HashSet删掉)
// 创建多级目录
File file2 = new File("c:\\temp\\tempp\\HashSet", "HashSet");
// 判断这个文件是否存在
if (!file2.exists()) {
file2.mkdirs();
}
运行后:

代码3:
创建文件:
createNewFile():创建文件// 创建文件
File file = new File("c:\\temp\\score1.txt");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
运行:

ps:若代码3中参数路径为:"c:\\temp\\score1",则会创建一个没有拓展名的文件。
假设这是当前位置:

它的绝对路径是:c:\\temp\\tempp\\1.txt
因为现在就在tempp这个文件夹下,所以1.txt的相对目录是:1.txt
tempp的上级目录如下:

想在以temp为当前位置的位置找到1.txt,相对路径为:tempp\\1.txt
访问上一层目录的方法:..\\
访问上两层:..\\..\\
在Eclipse下:
执行代码:
//创建文件
File f=new File("temp.txt");
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
会在工程目录下出现一个temp.txt

判断一个路径是绝对路径还是相对路径: isAbsolute():若是绝对路径,则返回true
获取路径
getPah():获得File构造方法参数表示的路径,也就是内容与File构造方法参数一致getAbsolutePath():获取绝对路径代码:
File f=new File("temp.txt");
try {
f.createNewFile();
//是否绝对路径
System.out.println(f.isAbsolute());
//获取相对路径
System.out.println(f.getPath());
//获取绝对路径
System.out.println(f.getAbsolutePath());
//获取文件名
System.out.println(f.getName());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
输出:
false
temp.txt
D:\eclipse\allProj\temp.txt
temp.txt
InputStreamOutputStream字节输入流InputStream包括:
FileInputStreamPipedInputStreamFilterInputStreamObjectInputStreamSequenceInputStreamByteArrayInputStreamStringBufferInputStream过滤器输入流FilterInputStream包括:
PushbackInputStreamBufferedInputStreamDataInputStream字节输出流OutputStream包括:
FileOutputStreamPipedOutputStreamFilterOutputStreamObjectOutputStreamByteArrayOutputStream过滤器输出流FilterOutputStream包括:
PrintStreamBufferedOutputStreamDataOutputStream文档如下:

构造方法

重要方法
| 方法名 | 描述 |
|---|---|
public int read() | 从输入流中读取一个数据字节 |
public int read(byte[] b) | 从输入流中将最多b.length个字节的数据读入一个byte数组中 |
public int read(byte[] b,int off,int len) | 从输入流中将最多len个字节的数据读入一个byte数组中 |
public int close() | 关闭此文件输入流并释放与此流有关的所有系统资源 |
若返回值为-1,则表达已经达到文件末尾。
代码演示:
我们在工程目录下有一个temp.txt文件:我们想要读取它。

代码(无参的read()):
public static void main(String[] args) {
try {
// 创建一个FileInputStream对象:要捕获FileNotFoundException异常
FileInputStream fis = new FileInputStream("temp.txt");
// 读取文件内容read:要捕获IOException异常
int n;
while ((n = fis.read()) != -1) {
System.out.print((char) n);
}
fis.close();// 关闭输入流,释放资源
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {// IOException是FileNotFoundException的父类
e.printStackTrace();
}
}
}
输出:asd123345
核心代码:
int n;
while ((n = fis.read()) != -1) {
System.out.print((char) n);
}
也可以是这样(但是重复了):
int n = fis.read();
while (n != -1) {
System.out.print((char) n);
n = fis.read();
}
int read(byte[] b)的代码——把核心代码替换成:
//读取数据,存放到一个byte类型的数组中
byte[] b=new byte[100];
fis.read(b);
System.out.println(new String(b));
fis.close();
输出:asd123345
若把fis.read(b);改成fis.read(b,0,6);,则输出:asd123
第二个参数表示偏移量:从byte数组的第几个开始存数据。
第三个参数表示要读取的字符个数。
若第二个参数改为1,则输出: asd123,前面空了一格。
用来将数据写入到文件中。
构造方法:

重要方法
| 方法名 | 描述 |
|---|---|
public void write(int b) | 将指定字节写入文件输出流 |
public void write(byte[] b) | 将b.length个字节从byte数组写入文件输出流 |
public void write(byte[] b,int off,int len) | 将指定byte数组中从偏移量off开始的len个字节写入文件输出流 |
public void close() | 关闭此文件输出流并释放与此流有关的所有系统资源 |
代码:
public class FileOutputDemo {
public static void main(String[] args) {
FileOutputStream fos;
FileInputStream fis;
try {
fos = new FileOutputStream("temp.txt");
fis = new FileInputStream("temp.txt");
//写入文件
fos.write(51);
fos.write('a');
//读取写入的文件
System.out.print(fis.read());
System.out.print((char) fis.read());
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出:51a
文件:因为编码原因,显示会不一样,但由输出我们可以知道写入的就是我们想要的51a

如果把fos = new FileOutputStream("temp.txt");改成fos = new FileOutputStream("temp.txt",true);,再运行一次,则文件内容为:3a3a。
原因:
FileOutputStream(File file, boolean append)
Creates a file output stream to write to the file represented by the specified File object.
由上述例子可知,文件输入输出流是不太适合做和字符相关的工作的。
我们再来看一个文件拷贝的例子。我们在工程目录下有一个jpg文件a,我们想把它拷贝到a_copy上。
复制粘贴其实就是读取和写入。
代码:
public static void main(String[] args) {
try {
// 文件拷贝
FileInputStream fis = new FileInputStream("a.jpg");
FileOutputStream fos = new FileOutputStream("a_copy.jpg");
int n = 0;// 存储read方法的返回值
byte[] b = new byte[1024];//一次读1024个字节
while ((n = fis.read(b)) != -1) {
fos.write(b);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
运行后:

注意:fos.write(b,0,n);可以保证拷贝后的文件大小一致——因为副本文件可能比原来的文件大,这是由一次拷贝b个字节造成的(剩下的文件字节小于b个时,就会使得拷贝后的文件大一点)
BufferedInputStreamBufferedOutputStream缓冲输入流相关方法:

缓冲输出流相关方法:

缓冲区满了会自动触发write()方法。
flush():清空缓冲区数据,使之触发write()方法代码(注释很详细):
public class BufferedDemo1 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("temp.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
FileInputStream fis = new FileInputStream("temp.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
// 写
bos.write(50);
bos.write('a');
// 运行,发现temp.txt是空的,说明数据还在缓冲区里
// 缓冲区未满,没有触发自动write操作
// 强制清空,会触发写操作
bos.flush();
// 运行后,temp.txt就有2a了
// 读取
System.out.println(bis.read());
System.out.println((char) bis.read());
// 实际上,关闭缓冲区也会触发写操作
bos.close();
// 关闭所有流
bis.close();
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件内容:2a
输出:
50
a
ReaderWriter字符输入流:

字符输出流:

InputStreamReaderOutputStreamReader相关方法:


代码演示:
输入流:我们想读取文件如下:

代码:两个方法都可以
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("temp.txt");
InputStreamReader isr = new InputStreamReader(fis);
// 读取数据
// 方法1
int n = 0;
char[] c = new char[10];
while ((n = isr.read()) != -1) {
System.out.print((char) n);
}
// 方法2
int n1 = 0;
while ((n1 = isr.read(c)) != -1) {
String str = new String(c, 0, n1);// n1表示要转换实际存储的字符数量
System.out.print(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
输出:
123
asdzxc
fgh
输出流:
我们想把temp.txt的内容读出来,然后写到tempp.txt中。
代码:
public class ReaderDemo {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("temp.txt");
InputStreamReader isr = new InputStreamReader(fis);
FileOutputStream fos = new FileOutputStream("tempp.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos);
// 读取数据
char[] c = new char[10];
int n1 = 0;
while ((n1 = isr.read(c)) != -1) {
// 写字符串
String str = new String(c, 0, n1);// n1表示要转换实际存储的字符数量
osw.write(str);
// 或者写字符数组
// osw.write(c,0,n1);
}
// 清空缓存
osw.flush();
// 关闭流
fis.close();
fos.close();
isr.close();
osw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行后:

关于编码:输入输出的编码要相同,不然会乱码。
构造函数中,String charsetName是字符集,在这里可以写想要的编码形式,如"GBK","UTF-8"
InputStreamReader(InputStream in, String charsetName)
Creates an InputStreamReader that uses the named charset.
OutputStreamWriter(OutputStream out, String charsetName)
Creates an OutputStreamWriter that uses the named charset.
代码:
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("temp.txt");
InputStreamReader isr = new InputStreamReader(fis, "GBK");
BufferedReader br = new BufferedReader(isr);
FileOutputStream fos = new FileOutputStream("tempp.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
BufferedWriter bw = new BufferedWriter(osw);
// 读取数据
char[] c = new char[10];
int n1 = 0;
while ((n1 = br.read(c)) != -1) {
// 写字符串
// String str = new String(c, 0, n1);// n1表示要转换实际存储的字符数量
// bw.write(str);
// 或者写字符数组
bw.write(c, 0, n1);
}
// 清空缓存
bw.flush();
// 关闭流
fis.close();
fos.close();
isr.close();
osw.close();
br.close();
bw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
运行后:

序列化:把Java对象转换为字节序列的过程。——写
反序列化:把字节序列恢复为Java序列的过程。——读
步骤:
Serializable接口相关类:
ObjectInputStreamObjectOutputStream需求:把Goods类的对象写入文件temp.txt中,然后再读取出来。
代码:
Goods类:
public class Goods implements Serializable {
private String GoodsId;
private String GoodsName;
private double price;
public Goods(String goodsId, String goodsName, double price) {
GoodsId = goodsId;
GoodsName = goodsName;
this.price = price;
}
public String getGoodsId() {
return GoodsId;
}
public void setGoodsId(String goodsId) {
GoodsId = goodsId;
}
public String getGoodsName() {
return GoodsName;
}
public void setGoodsName(String goodsName) {
GoodsName = goodsName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods [GoodsId=" + GoodsId + ", GoodsName=" + GoodsName + ", price=" + price + "]";
}
}
测试类:
public class GoodsTest {
public static void main(String[] args) {
// 定义一个Goods对象
Goods goods1 = new Goods("1", "电脑", 3000);
// 定义输入输出流
try {
FileOutputStream fos = new FileOutputStream("temp.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(goods1);
oos.flush();
// 关闭流
oos.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行后:

文件乱码,于是我们把它读取试试。
代码:
// 读取文件
FileInputStream fis = new FileInputStream("temp.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
try {
Goods goods = (Goods) ois.readObject();
System.out.println(goods);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
输出:Goods [GoodsId=1, GoodsName=电脑, price=3000.0]