流:程序(内存)与存储设备之间传输数据的通道。
如果区分不清楚in与out的方向,且记住,以程序为中心,从文件或者其他地方读数据到程序中,就是输入流,就用FileInputStream,从程序中将数据写到文件或者磁盘中,就是输出流,就用FileOutputStream。
简单的文件读写操作demo:
public static void fileInputStreamDemo() throws Exception {
System.out.println("单字节读取");
FileInputStream fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\in.txt");
int data;
while((data = fis.read()) != -1) {
System.out.println(data);
}
fis.close();
System.out.println("多字节读取");
fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\in.txt");
byte[] buf = new byte[3];
int count = 0;
while((count = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
fis.close();
}
public static void fileOutputStreamDemo() throws Exception {
System.out.println("单字节写入");
FileOutputStream fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\out.txt");
fos.write(97);
fos.write('b');
fos.write('c');
fos.close();
System.out.println("多字节写入");
String s = "hello, changsha";
fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\out.txt", true);
fos.write(s.getBytes());
fos.close();
}
/**
* 字节流实现文件的复制
*/
public static void fileCopyPicture() throws Exception {
FileInputStream fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\p1.JPG");
FileOutputStream fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\p2.JPG");
byte[] buf = new byte[1024];
int count;
while((count = fis.read(buf)) != -1) {
fos.write(buf, 0, count);
}
fos.close();
fis.close();
}
带有缓冲区的文件读写操作,缓冲流会自动关闭节点流,demo如下:
/**
* 字节输入缓冲流
*
* @throws Exception
*/
public static void fileBufferedInputStream() throws Exception {
FileInputStream fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\in.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buf = new byte[64];
int count;
while((count = bis.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
bis.close(); // 这里只需要关闭bis就行,bis.close会包含fis.close。
}
/**
* 字节输出缓冲流
*
* @throws Exception
*/
public static void fileBufferedOutputStream() throws Exception {
FileOutputStream fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\FileInputOutputStream\\outbuffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
// 写入文件
for (int i = 0; i < 100; i++) {
String s = "abcdefghijklmnopqrstuvwxyz\r\n";
bos.write(s.getBytes()); // 写入8k缓冲区
bos.flush(); // 刷新到硬盘
}
bos.close(); // 在关闭的时候会调用fis.close,也会调用flush操作,确保在关闭前将所有数据都写入了磁盘
}
对象流的作用:
增强缓冲区功能;
增强了基本数据类型和字符串的读写功能;
增强了读写对象的功能:
反序列化:readObject()是从流中读取一个对象
序列化:writeObject(Object obj)是向流中写入一个对象
demo如下:
/**
* ObjectOutputStream实现序列化
* 要求:序列化的类必须要实现Serializable接口
* 如果序列化类中还存有对象,则该对象也要实现Serializable接口
*/
public static void objectOutputStreamDemo() throws Exception {
FileOutputStream fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\ObjectInputOutputStream\\out.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Student student = new Student("王散", 20);
oos.writeObject(student);
oos.close();
}
/**
* ObjectInputStream实现序列化
* 要求:序列化的类必须要实现Serializable接口
* 如果序列化类中还存有对象,则该对象也要实现Serializable接口
*/
public static void objectInputStreamDemo() throws Exception {
FileInputStream fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\ObjectInputOutputStream\\out.bin");
ObjectInputStream ois = new ObjectInputStream(fis);
Student student = (Student)ois.readObject();
System.out.println(student.toString());
ois.close();
}
字节流虽然能处理一切文件,但是当它按照字节读取中文时,却可能会遇到打印乱码的问题,因此,在特定场景下,需要使用字符流,demo如下:
public static void fileReaderDemo() throws Exception {
FileReader fr = new FileReader("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\read.txt");
// 单个字符读取,采用utf-8,每次读三个字节
int data = 0;
while((data = fr.read()) != -1) {
System.out.println((char)data);
}
fr.close();
fr = new FileReader("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\read.txt");
// 多个个字符读取
char[] buf = new char[1024];
int count = 0;
while((count = fr.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
fr.close();
}
public static void fileWriteDemo() throws Exception {
// 写入
FileWriter fw = new FileWriter("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\write.txt");
for(int i = 0; i < 10; i++) {
fw.write("测试\n");
fw.flush();
}
fw.close();
}
/**
* 赋值文本文件
*/
public static void fileCopyDemo() throws Exception {
FileReader fr = new FileReader("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\read.txt");
FileWriter fw = new FileWriter("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\write.txt");
// 多个个字符读取
char[] buf = new char[1024];
int count = 0;
while((count = fr.read(buf)) != -1) {
fw.write(buf, 0, count);
fw.flush();
}
fw.close();
fr.close();
}
字符流也有缓冲流,demo如下:
/**
* 字符缓冲流
*/
public static void bufferedReader() throws Exception {
FileReader fr = new FileReader("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\read.txt");
BufferedReader br = new BufferedReader(fr);
char[] buf = new char[1024];
int count;
while((count = br.read(buf)) != -1) {
System.out.println(new String(buf, 0, count));
}
br.close();
fr = new FileReader("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\read.txt");
br = new BufferedReader(fr);
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
public static void bufferedWrite() throws Exception {
FileWriter fw = new FileWriter("D:\\Code\\QianFeng\\IO\\src\\FileCharStram\\write.txt");
BufferedWriter bw = new BufferedWriter(fw);
for(int i = 0; i < 10; i++) {
bw.write(i + "天道酬勤");
bw.newLine();
bw.flush();
}
bw.close();
}
打印流printStream:
封装了print/println方法,支持写入后换行;支持数据原样打印,即是什么数据就打印什么数据,demo如下:
public static void printfStream() throws Exception {
PrintStream ps = new PrintStream("D:\\Code\\QianFeng\\IO\\src\\PrintfStream\\print.txt");
ps.println(123);
ps.println(true);
ps.println('A');
ps.println("你好");
ps.println(3.1415926);
ps.close();
}
转换流:
可实现字节流与字符流的相互转换,也可设置字符的编码方式。
demo如下:
/**
* InputStreamReader 字节流-->字符流
*/
public static void inputStreamReader() throws Exception {
FileInputStream fis = new FileInputStream("D:\\Code\\QianFeng\\IO\\src\\IOStreamReaderWriter\\in.txt");
InputStreamReader isr = new InputStreamReader(fis, "utf-8");
int data = 0;
while ((data = isr.read()) != -1) {
System.out.print((char)data);
}
isr.close();
}
/**
* OutputStreamWriter 字符流-->字节流
*/
public static void outputStreamReader() throws Exception{
FileOutputStream fos = new FileOutputStream("D:\\Code\\QianFeng\\IO\\src\\IOStreamReaderWriter\\out.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "utf-8");
int data = 0;
for(int i = 0; i < 10; i++) {
osw.write(i + "老骥伏枥,志在千里\r\n");
}
osw.close();
}
文件操作:
demo如下:
public static void fileTest() throws Exception {
// 分隔符
System.out.println("目录分隔符:" + File.pathSeparator);
System.out.println("文件分隔符:" + File.separator);
// 文件操作
File file = new File("D:\\Code\\QianFeng\\IO\\src\\FileTest\\file.txt");
if(file.exists()) {
System.out.println("文件已经存在。不需要创建了");
} else {
boolean b = file.createNewFile();
if (b) {
System.out.println("文件创建成功!");
} else {
System.out.println("文件创建失败!");
}
}
// 方式1:直接删除
boolean b = file.delete();
if (b) {
System.out.println("文件删除成功!");
} else {
System.out.println("文件删除失败!");
}
// 方式2:jvm退出时自动删除
// file.deleteOnExit();
// 获取文件路径
System.out.println("文件绝对路径:" + file.getAbsolutePath());
System.out.println("文件:" + file.getAbsoluteFile());
System.out.println("文件的路径:" + file.getPath());
System.out.println("获取文件名称:" + file.getName());
System.out.println("获取父目录:" + file.getParent());
System.out.println("获取文件长度:" + file.length());
System.out.println("获取文件创建时间:" + new Date(file.lastModified()).toLocalDate());
System.out.println("文件是否可寫?" + file.canWrite());
System.out.println("是否是文件?" + file.isFile());
System.out.println("文件是否為隱藏文件?" + file.isHidden());
}