看看Java里面的IO
IO流
intput:输入流,从网络种读取文件到内存,磁盘里面读取文件到内存。
output:输出流,从内存里面读取文件显示在网络上面,内存的数据写到文件上面。
字节流
以byte为最小单位。
intputStream 输入字节流
outputStream 输出字节流
字符流
以char字符的方式去读写
如果文件是以文本的方式存在,用字符流方便
reader 读
writer 写
同步&异步
IO同步
这个CPU在等待现在正在进行的IO,必须等现在进行的IO执行完毕了。在去执行下一个IO。
IO操作的时候,必须等待数据返回!才能执行下面的代码。
IO异步
IO操作的时候,不需要等待数据返回!就可以执行下面的代码
在java.io里面都是同步IO
在java.nio里面都是异步IO
File 文件对象
package com.hu.io_;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
public class FileDome {
public static void main(String[] args) throws IOException{
/*
* 创建一个file里面可以放入绝对路径和相对路径
* 绝对路径:以根目录为开头的例如:C:\\a\\a.txt
* 相对路径:取出掉绝对路径的目录就是相当路径例如:a\\a.txt
*
* File:有三种表示路径的方式
* file.getPath(): 返回构造器里面的路径
* file.getAbsolutePath(): 返回绝对路径
* file.getCanonicalPath(): 返回规范路径
*规范路径就是:把.和.. 当前级和返回上一级给表现出来。
*
* File是一个文件对象,他也可以表示一个目录对象。
* isFile() 判断是否是一个文件
* isDirectory() 判断是否是一个目录
* 用File对象获取到一个文件时,还可以进一步判断文件的权限和大小:
boolean canRead():是否可读;
boolean canWrite():是否可写;
boolean canExecute():是否可执行;
long length():文件字节大小。
创建和删除文件:
file.createNewFile();
file.delete();
* Java里面提供了一个创建临时文件的
* File.createTempFile("tmp-", ".txt"); // 提供临时文件的前缀和后缀
deleteOnExit(); // JVM退出时自动删除
遍历文件或目录
当File对象表示一个目录时,可以使用list()和listFiles()列出目录下的文件和子目录名
File[] files = file.listFiles(); 返回当前目录下的所有文件
* File[] fs2 = file.listFiles(new FilenameFilter() { // 仅列出.exe文件
public boolean accept(File dir, String name) {
return name.endsWith(".txt"); // 返回true表示接受该文件
}
});返回当前目录下面的txt后缀名的文件
* 如何创建一个目录
File file = new File("C:\\ABC");
if(file.mkdirs()){
System.out.println("创建成功!");
}
* 如何删除这个目录
*
* */
File file = new File("C:\\ABC");
if(file.delete()){
System.out.println("cs成功!");
}
// File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit");
//
// File[] files = file.listFiles();
// printFiles(files);
// File[] fs2 = file.listFiles(new FilenameFilter() { // 仅列出.exe文件
// public boolean accept(File dir, String name) {
// return name.endsWith(".txt"); // 返回true表示接受该文件
// }
// });
// printFiles(fs2);
// File f = File.createTempFile("abc", ".txt");
//
// f.deleteOnExit();
// System.out.println(f.getAbsolutePath());
// File file = new File("..");
// System.out.println(file.getPath());
// System.out.println(file.getAbsolutePath());
// System.out.println(file.getCanonicalPath());
// File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit\\wd.txt");
// System.out.println(file.isFile());//T
// System.out.println(file.isDirectory());//F
// File file = new File("D:\\User\\hupenglong.UCO\\Desktop\\demoGit\\wd");
// file.createNewFile();
// file.delete();
//System.out.println(File.separator); // 根据当前平台打印"\"或"/"
}
static void printFiles(File[] files) {
System.out.println("==========");
if (files != null) {
for (File f : files) {
System.out.println(f);
}
}
System.out.println("==========");
}
}
<di> </di>遍历一个文件夹下面所有的文件
public void selectFile(File file){
Files[] fs = file.listFiles();
for(int i = 0; i < fs.length;i++){
if(fs[i].isDirectory()){
selectFile(fs[i]);
}else{
System.out.println(fs);
}
}
} InputStream
InputStream是一个抽象类,是输入IO里面的基类。
这一个read方法非常重要
public abstract int read() throws IOException;
去读取数据,读数据的下一行并且返回一个【0~255】的数字,如果读带最后一行返回-1
根据以上案例如何去读一个文件
一直去读嘛,然后返回值是-1停止。记得关闭资源
Java7的引入的语法
//用try ... finally来编写上述代码会感觉比较复杂,更好的写法是利用Java 7引入的新的try(resource)的语法,只需要编写try语句,让编译器自动为我们关闭资源。推荐的写法如下:
public void readFile() throws IOException {
try (InputStream input = new FileInputStream("src/readme.txt")) {
int n;
while ((n = input.read()) != -1) {
System.out.println(n);
}
} // 编译器在此自动为我们写入finally并调用close()
}
//实际上,编译器并不会特别地为InputStream加上自动关闭。编译器只看try(resource = ...)中的对象是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally语句并调用close()方法。InputStream和OutputStream都实现了这个接口,因此,都可以用在try(resource)中。 缓冲
一个一个读取太慢了。我们可以先读取一部分放在一个容器里面
就是一次性读取多个字节,InputStream里面提供两个重载的方法
- int read(byte[] b):读取若干字节并填充到byte[]数组,返回读取的字节数
- int read(byte[] b, int off, int len):指定byte[]数组的偏移量和最大填充数
阻塞
我们的是同步IO的,所以在读的时候不知道要等多久
OutputStream
是基本输出IO,他的输出差不多
public abstract void write(int b) throws IOException;
虽然是int类型的参数,不过他只写入一个字节的。
这里面有一个fluch(),和缓存差不多就是写的时候一个一个写太慢了。先写在一个容器里面在一次性写出去。
我们来实现一下文件的复制
基本原理就是读一个文件,同时去写一个文件。
package com.hu.io_;
import java.io.*;
public class Text3 {
public static void main(String[] args) {
InputStream input = null;
OutputStream output = null;
try{
input = new FileInputStream("D:\\User\\hupenglong.UCO\\Desktop\\t\\a.txt");
output = new FileOutputStream("D:\\User\\hupenglong.UCO\\Desktop\\t\\b.txt");
while(true){
int n = input.read();
output.write(n);
if(n == -1){
break;
}
System.out.println(n);
}
}catch(IOException e){
System.out.println(e);
}
finally{
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Filter 模式 这就是装饰器模式
FileinputStream 如果给他添加一个缓存
FileinputStream 如果给他添加一个加密
FileinputStream 如果给他添加一个签名
我们都需要添加一个类去继承FileinputStream,这种子类太多了非常麻烦!
但是我们可以子类引用指向父类。
InputStream in = new FileInputStream("test.gz");
InputStream in = new 其他的子类,
通过少量的类,来实现工作功能组合
我们编写一个自己这对于IO流的功能的
public class Main {
public static void main(String[] args) throws IOException {
byte[] data = "hello, world!".getBytes("UTF-8");
try (CountInputStream input = new CountInputStream(new ByteArrayInputStream(data))) {
int n;
while ((n = input.read()) != -1) {
System.out.println((char)n);
}
System.out.println("Total read " + input.getBytesRead() + " bytes");
}
}
}
//CountInputStream,它的作用是对输入的字节进行计数:
class CountInputStream extends FilterInputStream {
private int count = 0;
CountInputStream(InputStream in) {
super(in);
}
public int getBytesRead() {
return this.count;
}
public int read() throws IOException {
int n = in.read();
if (n != -1) {
this.count ++;
}
return n;
}
public int read(byte[] b, int off, int len) throws IOException {
int n = in.read(b, off, len);
if (n != -1) {
this.count += n;
}
return n;
}
}
序列化
序列化,就是把Java对象变成为一个byte[] 二进制数据,然后这样就方便在网络上传输了
一个类要实现这种操作,必须实现Serializable 接口
ClassPath路径
我们在读取一个文件的时候要根据文件的路径去读,但是操作系统不同读取的文件路径就是不同的这样就很麻烦