IO流
- IO流
- java.io下需要掌握的16个流
- 文件专属
- java.io.FileInputStream(重点)
- java.io.FileOutputStream(重点)
- java.io.FileReader
- java.io.FileInWhiter
- 转换流
- java.io.InputStreamReader
- java.io.OutputStreamReader
- 缓冲流专属
- java.io.BufferedReader
- java.io.BufferedWriter
- java.io.BufferedInputStream
- java.io.BufferedOutputStream
- 数据流专属
- java.io.DataInputStream
- java.io.DataOutputStream
- 标准输出流
- java.io.PrintWriter
- java.io.PrintStream(重点)
- 对象专属流:
- java.io.ObjectInputStream(重点)
- java.io.ObjectOutputStream(重点)
- java.io.File类
IO流
java中所有的流都是在:java.io.*;下。
java.io.InputStream
字节输入流java.io.OutputStream
字节输出流
java.io.Reader
字符输入流java.io.Writer
字符输出流
所有的流都实现了:java.io.Closeable
接口,都是可关闭的,都有close()方法。
流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
所有的输出流都实现了:java.io.Flushable
接口,都是可刷新的,都有flush()方法。
养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。
注意:如果没有flush()可能会导致丢失数据。
java.io下需要掌握的16个流
文件专属:
java.io.FileInputStream 文件字节输入流
java.io.FileOutputStream 文件字节输出流
java.io.FileReader 文件字符输入流
java.io.FileWhiter 文件字符输出流
转换流:
java.io.InputStreamReader 将输入字节流转换成输入字符流
java.io.OutputStreamReader 将输出字节流转换成输出字符流
缓冲流专属:
java.io.BufferedReader 带有缓冲区的字符输入流
java.io.BufferedWriter 带有缓冲区的字符输出流
java.io.BufferedInputStream 带有缓冲区的字节输入流
java.io.BufferedOutputStream 带有缓冲区的字节输出流
数据流专属:
java.io.DataInputStream 数据字节输入流
java.io.DataOutputStream 数据字节输出流
标准输出流:
java.io.PrintWriter 标准的字节输入流
java.io.PrintStream 标准的字节输出流
对象专属流:
java.io.ObjectInputStream
java.io.ObjectOutputStream
文件专属
java.io.FileInputStream(重点)
1.文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
2.字节的方式,完成输入的操作,完成读的操作(硬盘 --> 内存)
方法:
-
int read(byte[] b)
一次最多读取 b.length 个字节。
减少硬盘与内存的交互,提高程序的执行效率。
public class FileInputStreamTest {
public static void main(String[] args) {
FileInputStream fis = null;
try {
// 创建文件字节输入流对象
// 文件路径 E:\Users\DIY\IdeaProjects\JavaSE\567\temp
// 在IDEA中默认的当前路径是Project的根
//FileInputStream fis = new FileInputStream("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567\\temp");
// 也可以这样写
fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp");
// 读
/*int readData = fis.read(); // 这个方法返回的是:读取到的字节本身
System.out.println(readData); //97*/
/*while (true) {
int read = fis.read();
if (read == -1) break;
System.out.println(read); // 97 98 99
}*/
/*int readData = 0;
while ((readData = fis.read()) !=-1) {
System.out.println(readData); //97 98 99
}*/
// 采用byte数组,一次读取多个字节,最多读取"数组.length"个字节。
byte[] bytes = new byte[2];
/*int readCount = fis.read(bytes);// 这个方法返回的是:读取到的字节数量
System.out.println(readCount); //2 读取ab
// 将字节数组全部转换成字符串
System.out.println(new String(bytes)); //ab
// 应该是读到多少转换多少
System.out.println(new String(bytes,0,readCount)); //ab
readCount = fis.read(bytes);
System.out.println(readCount); //1 读取c
System.out.println(new String(bytes)); //cb
System.out.println(new String(bytes,0,readCount)); //c
readCount = fis.read(bytes);
System.out.println(readCount); //-1 没有读到*/
int readCount = 0;
while ((readCount = fis.read(bytes)) !=-1) {
System.out.print(new String(bytes,0,readCount)); //abc
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) { // 避免空指针异常
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
其他常用方法:
-
int available()
返回流当中剩余的没有读到的字节数量 -
long skip(long n)
跳过几个字节不读
public class FileInputStreamTest01 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
// 创建文件字节输入流对象
// 文件路径 E:\Users\DIY\IdeaProjects\JavaSE\567\temp
fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp");
System.out.println("总字节数" + fis.available()); //3
/*int readByte = fis.read();
// int available() 返回流当中剩余的没有读到的字节数量
System.out.println("剩下" + fis.available() + "字节没读"); //2*/
/*byte[] bytes = new byte[fis.available()]; // 这种方式不适合太大的文件,因为byte数组不能太大
fis.read(bytes); // 只需要读一次
System.out.println(new String(bytes)); //abc*/
// long skip(long n) 跳过几个字节不读
fis.skip(1); // 跳过1个不读
System.out.println(fis.read()); // 98
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) { // 避免空指针异常
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
java.io.FileOutputStream(重点)
文件字符输出流,负责写。
从内存到硬盘
public class FileOutputStreamTest {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
// 文件不存在会新建
// 这种方式会将原文件清空再重新写入
//fos = new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1");
// 这种方式以追加的方式在文件末尾写入,不会清空原文件内容
fos = new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1", true);
// 写
byte[] bytes = {97,98,99,100};
// 将byte数组全部写出
fos.write(bytes); // abcd
// 将byte数组的一部分写出
fos.write(bytes, 0 ,2); // 追加ab
String s = "我是中国人";
// 将字符串转换成byte数组
byte[] bytes1 = s.getBytes();
fos.write(bytes1);
// 写完之后,最后一定要刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
java.io.FileReader
文件字符输入流,只能读取普通文本。
读取文本内容时,比较方便、快捷。
用法跟FileInputStream差不多
public class FileReaderTest {
public static void main(String[] args) {
FileReader reader = null;
try {
// 创建文件字符输入流
reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/temp1");
// 读
char[] chars = new char[3]; //一次读取3个支付
int readCount = 0;
while ((readCount = reader.read(chars)) != -1) {
System.out.print(new String(chars,0,readCount)); //abcdab我是中国人
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
java.io.FileInWhiter
文件字符输出流。写。只能输出普通文本
用法跟FileOutputStream差不多
public class FileWriterTest {
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
// 创建文件字符输出流
//fileWriter = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/temp3");
// 不清空,直接进行追加
fileWriter = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/temp3",true);
// 写
char[] chars = {'你','好','世','界'};
fileWriter.write(chars); //你好世界
fileWriter.write(chars, 2, 2); //你好世界世界
fileWriter.write("你好呀"); //你好世界世界你好呀
// 刷新
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件拷贝
使用 FileReader + FileWriter 进行拷贝。只能拷贝普通文本
public class CopyTest {
public static void main(String[] args) {
FileReader reader = null;
FileWriter writer = null;
try {
// 创建文件字符输入流
reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/File.java");
// 创建文件字符输出流
writer = new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");
char[] chars = new char[1024 * 512]; //1MB
int readCount = 0;
while ((readCount = reader.read(chars)) != -1) {
writer.write(chars,0,readCount);
}
// 刷新
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
转换流
java.io.InputStreamReader
将输入字节流转换成输入字符流
java.io.OutputStreamReader
将输出字节流转换成输出字符流
缓冲流专属
java.io.BufferedReader
带有缓冲区的字符输入流。
使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲
public class BufferedReaderTest {
public static void main(String[] args) throws Exception {
// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流
// 外部负责包装的这个流叫做:包装流,又叫处理流
// 以下来说,FileReader就是一个节点流,BufferedReader就是包装流
/*FileReader reader = new FileReader("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");
BufferedReader br = new BufferedReader(reader);*/
/*// 字节流
FileInputStream fis = new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java");
// 通过转换流转换(InputStreamReader 将字节流转换成字符流)
// fis 是节点流,reader 是包装流。
InputStreamReader reader = new InputStreamReader(fis);
// 这个构造方法只能传一个字符流。不能传字节流
// reader 是节点流,br 是包装流。
BufferedReader br = new BufferedReader(reader);*/
// 合并
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java")));
// 读一行
/*System.out.println(br.readLine()); //package com.xxx.javase.filewriter;
System.out.println(br.readLine()); //
System.out.println(br.readLine()); //public class File {*/
String s = null;
while ((s = br.readLine()) != null) {
System.out.println(s);
}
// 关闭流
// 对于包装流来说,只需要关闭最外层的流就行,里面的节点流会自动关闭。
/* //源码如下
public BufferedReader(Reader in) {
this(in, defaultCharBufferSize);
}
public void close() throws IOException {
synchronized (lock) {
if (in == null) return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
*/
br.close();
}
}
java.io.BufferedWriter
带有缓冲区的字符输出流
public class BufferedWriterTest {
public static void main(String[] args) throws Exception {
// 带有缓冲区的字符输出流
//BufferedWriter bw = new BufferedWriter(new FileWriter("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java"));
// 将字符流转换成字节流
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/File1.java",true)));
// 写
bw.write("hello");
bw.write("\n");
bw.write("would");
// 刷新
bw.flush();
// 关闭流
bw.close();
}
}
java.io.BufferedInputStream
与BufferedReader用法类似
java.io.BufferedOutputStream
与BufferedWriter用法类似
数据流专属
java.io.DataInputStream
DataOutputStream写的文件,只能使用DataInputStream去读。并且要提前知道写入的顺序,读的顺序
需要和写的顺序一致
,才可以正常取出数据。
public class DataInputStreamTest {
public static void main(String[] args) throws Exception {
DataInputStream dis = new DataInputStream(new FileInputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/data"));
// 读
byte b = dis.readByte();
short s = dis.readShort();
int i = dis.readInt();
long l = dis.readLong();
float f = dis.readFloat();
double d = dis.readDouble();
boolean bl = dis.readBoolean();
char c = dis.readChar();
System.out.println(b); //10
System.out.println(s); //20
System.out.println(i); //30
System.out.println(l); //40
System.out.println(f); //1.0
System.out.println(d); //3.14
System.out.println(bl); //false
System.out.println(c); //a
dis.close();
}
}
java.io.DataOutputStream
这个流可以将数据连同数据的类型
一并写入文件。
注意:这个文件不是
普通文本文档(用记事本打不开)。
public class DataOutputStreamTest {
public static void main(String[] args) throws Exception {
// 创建数据专属的字节输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/data"));
byte b = 10;
short s = 20;
int i = 30;
long l = 40L;
float f = 1.0F;
double d = 3.14;
boolean sex = false;
char c = 'a';
// 写数据
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(sex);
dos.writeChar(c);
// 刷新
dos.flush();
// 关闭
dos.close();
}
}
标准输出流
java.io.PrintWriter
java.io.PrintStream(重点)
/*
java.io.PrintStream:标准的字节输出流。默认输出到控制台。
*/
public class PrintStreamTest {
public static void main(String[] args) throws Exception {
// 联合起来写
System.out.println("hello world!");
// 分开写
PrintStream ps = System.out;
ps.println("hello world1");
// 标准输出流不需要手动close()关闭。
// 可以改变标准输出流的输出方向
// 标准输出流不指向控制台,指向"log"文件
PrintStream printStream = new PrintStream(new FileOutputStream("E:/Users/DIY/IdeaProjects/JavaSE/567/log"));
// 修改输出方向,将输出方向修改到"log"文件
System.setOut(printStream);
// 再输出
System.out.println("hello world2");
}
}
对象专属流:
java.io.ObjectInputStream(重点)
java.io.ObjectOutputStream(重点)
java.io.File类
File类的常用方法
/*
File对象代表文件和目录路径名的抽象表示形式。
*/
public class FileTest {
public static void main(String[] args) throws IOException {
File file = new File("E:\\file");
// 判断是否存在
System.out.println(file.exists());
// 如果D:\file不存在,则以文件的形式创建出来
/*if (!file.exists()) {
file.createNewFile();
}*/
// 如果D:\file不存在,则以目录的形式创建出来
/*if (!file.exists()) {
file.mkdir();
}*/
File file1 = new File("E:/a/s/d");
// 以多重目录的形式创建
/*if (!file1.exists()) {
file1.mkdirs();
}*/
File file2 = new File("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567\\temp");
// 获取文件名
System.out.println("获取文件名:" + file2.getName()); //temp
// 判断是否是一个目录
System.out.println(file2.isDirectory()); //false
// 判断是否是一个文件
System.out.println(file2.isFile()); //true
// 获取文件最后一次修改时间
long millisecond = file2.lastModified(); //返回的是从1970年到现在的总毫秒数
// 将总毫秒数转换成日期
Date data = new Date(millisecond);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime = sdf.format(data);
System.out.println(strTime); //2022-04-08 10:26:24 105
// 获取文件大小
System.out.println(file2.length() + "字节"); //3字节
// 获取文件的父路径
System.out.println(file2.getParent()); //E:\Users\DIY\IdeaProjects\JavaSE\567
File parentFile = file2.getParentFile();
System.out.println("获取绝对路径:" + parentFile.getAbsolutePath()); //E:\Users\DIY\IdeaProjects\JavaSE\567
File file3 = new File("temp1");
// 获取绝对路径
System.out.println("获取绝对路径:" + file3.getAbsolutePath()); //E:\Users\DIY\IdeaProjects\JavaSE\530\temp1
File file4 = new File("E:\\Users\\DIY\\IdeaProjects\\JavaSE\\567");
// File[] listFiles() 获取当前目录下所有的子文件
File[] files = file4.listFiles();
// 遍历
for (File file5 : files) {
// 获取绝对路径
//System.out.println(file5.getAbsolutePath());
// 获取文件名
System.out.println(file5.getName());
}
}
}