一.流的分类与理解
二.IO流的类库
三.所有的流都需要close,输出流需要flush(flush:将输出流的数据强制写出,即清空输出流,防止数据丢失)
四.使用文件字节输入流读取文件
public class FileInputStreamTest01 {
// 使用java.io.FileInputStream来读取一个文件。
// 这个流是字节流,一次只能读取一个字节。(8个二进制位)
public static void main(String[] args) {
long begin = System.currentTimeMillis();
FileInputStream fis = null;
try {
// 以下两种方式都是绝对路径。
//FileInputStream fis = new FileInputStream("D:\\powernode\\java_manhua\\java_manhua\\data.txt");
//FileInputStream fis = new FileInputStream("D:/powernode/java_manhua/java_manhua/data.txt");
// 相对路径怎么写?
// IDEA工具默认的当前路径是工程的根。
fis = new FileInputStream("data.txt");
int readByte = 0;
while((readByte = fis.read()) != -1){
//System.out.println(readByte);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end - begin)+"毫秒");
}
}
五.BufferedInputStream流提高读性能
public class BufferedInputStreamTest01 {
// 使用BufferedInputStream提高读的性能
// 内存和硬盘之间的交互次数越少,效率越高。
// BufferedInputStream:是一个字节流。是一个输入流,负责读的。Buffered被翻译为缓存。
// 这个流会在内存当中自备一个byte数组,这个byte数组就是一种缓存机制,然后一次性读取多个字节。
// 放到缓存当中。减少内存和硬盘的交互。提高读的效率。
/*
public BufferedInputStream(InputStream in) {
this(in, DEFAULT_BUFFER_SIZE);
}
这是BufferedInputStream的构造方法。
BufferedInputStream流可以看做是包装流/处理流。
参数InputStream流可以看做节点流。
其实这里体现了一种设计模式:装饰模式。(GoF23种设计模式中的一种。)
*/
public static void main(String[] args) {
long begin = System.currentTimeMillis();
BufferedInputStream bis = null;
try {
// 节点流
FileInputStream fis = new FileInputStream("data.txt");
// 包装流
bis = new BufferedInputStream(fis);
int readByte = 0;
while((readByte = bis.read()) != -1){
System.out.println(readByte);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 只需要关闭最外层的包装流。
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println("耗时"+(end - begin)+"毫秒");
}
}
六.DataInputStream的使用
public class DataInputOutputTest {
/*
1.DataOutputStream和DataInputStream是配合使用的。
2.只有使用DataOutputStream流写的文件,DataInputStream才能读。
3.DataOutputStream在写的时候,会连同类型一块写入到文件当中。
DataInputStream在读的时候,也会连同类型一块读入到内存当中。
*/
public static void main(String[] args) {
//写入!!!
/*DataOutputStream dos = null;
try {
// 创建DataOutputStream流,负责写。
FileOutputStream fos = new FileOutputStream("d.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
dos = new DataOutputStream(bos);
// 开始写
dos.writeBoolean(true);
dos.writeDouble(3.14);
// 记得刷新
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
//读取!!!
// 使用它的兄弟:DataInputStream来读取这个文件
DataInputStream dis = null;
try {
FileInputStream fis = new FileInputStream("d.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
// 开始读
// 读的时候要注意:读的顺序和写的顺序必须一样。
boolean b = dis.readBoolean();
System.out.println(b);
double v = dis.readDouble();
System.out.println(v);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
七.BufferedOutputStream流提高写性能
public class DataInputOutputTest {
/*
1.DataOutputStream和DataInputStream是配合使用的。
2.只有使用DataOutputStream流写的文件,DataInputStream才能读。
3.DataOutputStream在写的时候,会连同类型一块写入到文件当中。
DataInputStream在读的时候,也会连同类型一块读入到内存当中。
*/
public static void main(String[] args) {
/*DataOutputStream dos = null;
try {
// 创建DataOutputStream流,负责写。
FileOutputStream fos = new FileOutputStream("d.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
dos = new DataOutputStream(bos);
// 开始写
dos.writeBoolean(true);
dos.writeDouble(3.14);
// 记得刷新
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
// 使用它的兄弟:DataInputStream来读取这个文件
DataInputStream dis = null;
try {
FileInputStream fis = new FileInputStream("d.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
// 开始读
// 读的时候要注意:读的顺序和写的顺序必须一样。
boolean b = dis.readBoolean();
System.out.println(b);
double v = dis.readDouble();
System.out.println(v);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis != null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
八.PrintStream流的使用
public class PrintStreamTest {
// PrintStream流的使用,PrintStream流是自动刷新
// PrintStream流是一个标准输出流。
public static void main(String[] args) throws Exception{
System.out.println("Hello World!");
// 将以上代码拆分为下面两行,可以看到System.out居然返回了一个PrintStream流对象。
// 标准的输出流对象默认是向控制台打印信息。
PrintStream ps = System.out;
ps.println("Hello World!");
// 可以自定义标准输出流的输出方向。(程序员是可以干预的。)
// 创建PrintStream对象
FileOutputStream fos = new FileOutputStream("logfile.txt", true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
PrintStream pout = new PrintStream(bos);
//PrintStream pout = new PrintStream(fos);
// 改变标准输出流的方向。
System.setOut(pout);
System.out.println("Hello World!");
System.out.println("Hello World!");
System.out.println("Hello World!");
System.out.println("Hello World!");
System.out.println("Hello World!");
// 如果使用的是缓冲流的话,这个刷新就需要自己刷新了。
pout.flush();
}
}
九.InputStreamReader解决读的乱码问题
public class InputStreamReaderTest {
public static void main(String[] args) throws Exception{
// 读取D:/a.txt文件,这个文件目前的字符集是GBK的方式。
FileInputStream fis = new FileInputStream("D:/a.txt");
// InputStreamReader他是一个字符流。
// InputStreamReader他也是一个转换流:将字节流转换成字符流。
// java程序是基于Unicode方式,UTF-8的方式读取这个文件的。有问题吗?
// 解决乱码问题两种方案:
// 第一种:将a.txt的字符集修改为UTF-8
// 第二种:创建InputStreamReader流的时候,指定读取的字符集。
InputStreamReader reader = new InputStreamReader(fis, "GBK");
// 开始读
System.out.println((char)reader.read());
// 关闭流
reader.close();
}
}
十.BufferedReader的使用
public class BufferedReaderTest {
// BufferedReader类的使用
// 带有缓冲区的字符流。
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new FileReader("logfile.txt"));
String s = null;
while((s = br.readLine()) != null) {
System.out.println(s);
}
br.close();
}
}
十一.OutputStreamWriter解决写的乱码问题
public class OutputStreamWriterTest {
//采用指定字符集的方式写文件
public static void main(String[] args) throws Exception{
// a.txt文件是GBK的字符集。
FileOutputStream fos = new FileOutputStream("D:/a.txt", true);
// 创建转换流
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
// 写
osw.write("大家好,欢迎大家学习漫画Java编程!");
// 刷新
osw.flush();
// 关闭
osw.close();
}
}
十二.实现文件拷贝
public class CopyFile {
public static void main(String[] args) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 拷贝文件
// 为了拷贝任何类型的文件,我们这里采用字节流进行拷贝。
// 一边读一遍写。(FileInputStream FileOutputStream)
// 创建输入流和输出流
FileInputStream fis = new FileInputStream("D:/1.jpg");
bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("D:/2.jpg");
bos = new BufferedOutputStream(fos);
// 一遍读一遍写
int readByte = 0;
while((readByte = bis.read()) != -1) {
bos.write(readByte);
}
bos.flush();
} catch (IOException e){
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
十三.File类的使用
public class FileTest {
// File类的使用
// File不是IO流,通过它不能完成读和写。
// File是文件系统中 文件路径的 抽象表示。
// D:\java_manhua 虽然是一个目录,它也是一个File
// D:\java_manhua\data.txt 是一个文件,它也是一个File
// File实际上是一个路径的抽象表示形式。File既可以是一个目录,也可以是一个文件。
public static void main(String[] args) throws Exception{
/*
boolean exists():测试该 File 对象所代表的文件或者目录是否存在。
boolean mkdir():在文件系统中创建由该 File 对象表示的目录。
boolean createNewFile():如果该 File 对象代表文件,并且该文件在文件系统中不存在,就在文件系统中创建这个文件,内容为空。
boolean isDirectory():测试该 File 对象是否代表一个目录。
boolean isFile():测试该 File 对象是否代表一个文件。
String getPath():获取该 File 对象所代表的文件或者目录的路径。
String getName():获取该 File 对象所代表的文件或者目录的名字。
boolean delete():删除该 File 对象所代表的文件或者目录。如果 File 对象代表目录,并且目录下包含子目录或文件,则不允许删除 File 对象代表的目录。
String getParent():获取该 File 对象所代表的文件或者目录的根路径。如果没有根路径,就返回 null。
File[] listFiles():如果该 File 对象代表目录,则返回该目录下所有文件和目录的 File对象。
*/
/*// 创建File对象
File f1 = new File("D:/a");
// 如果d:/a目录不存在,则新建目录
if(!f1.exists()){
// 以目录的形式新建
//f1.mkdir();
// 以文件的形式新建
f1.createNewFile();
}*/
/*File f1 = new File("D:/a/b/c");
if(!f1.exists()){
f1.mkdirs();
}*/
/* File f1 = new File("d:/a/b/c");
System.out.println(f1.isDirectory()); // true
System.out.println(f1.isFile()); // false
System.out.println(f1.getPath());
System.out.println(f1.getName());
System.out.println(f1.getParent());
System.out.println(f1.getParentFile().getPath());
f1.delete();*/
// 获取当前目录下的所有子文件
File f1 = new File("D:\\java_manhua");
File[] files = f1.listFiles();
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
}
}
十四.使用nio下的子包file中的工具类
public class FileTool {
public void copyFile(String fromDir, String toDir,
String file) throws IOException {
Path pathFrom = Paths.get(fromDir, new String[]{file});
Path pathTo = Paths.get(toDir, new String[]{file});
// 复制文件,如果目标文件已经存在就将其覆盖
Files.copy(pathFrom, pathTo,
StandardCopyOption.REPLACE_EXISTING);
}
public void moveFile(String fromDir, String toDir,
String file) throws IOException {
Path pathFrom = Paths.get(fromDir, new String[]{file});
Path pathTo = Paths.get(toDir, new String[]{file});
// 移动文件,如果目标文件已经存在就将其覆盖
Files.move(pathFrom, pathTo,
StandardCopyOption.REPLACE_EXISTING);
}
public void list(String dir) throws IOException {
Path path = Paths.get(dir);
// 获得 path 目录下的所有文件和子目录,不包含子目录下的嵌套内容
DirectoryStream<Path> paths =
Files.newDirectoryStream(path);
for (Path p : paths)
System.out.println(p.getFileName());
}
public static void main(String[] args) throws IOException {
FileTool tool = new FileTool();
// 把 D:\mydir 目录下的 data.txt 文件复制到 D:\tmp 目录下
//tool.copyFile("D:\\mydir", "D:\\tmp", "data.txt");
// 把 D:\mydir 目录下的 data.txt 文件移动到 D:\tmp 目录下
//tool.moveFile("D:\\mydir", "D:\\tmp", "data.txt");
// 遍历 D:\mydir 目录下的内容
tool.list("D:\\java_manhua");
}
}
十五.遍历目录树
public class Test {
// 遍历目录树
public static void main(String[] args) {
String path = "D:\\java_manhua";
File f = new File(path);
walkFileTree(f);
}
private static void walkFileTree(File f) {
// 递归的结束条件
if (f.isFile()) {
return;
}
File[] files = f.listFiles();
for (File file : files){
System.out.println(file.getAbsolutePath());
walkFileTree(file);
}
}
}