1g File与IO.txt
UP 返回
1.java.io.File 重写了toString()
1.1 四个静态变量:
static String pathSeparator 路径分隔符 windows下是; Linux下是:
static char pathSeparatorChar 路径分隔符
static String separator 默认名称分隔符 windows下是\ Linux下是/
static char separatorChar 默认名称分隔符
1.2 路径 不区分大小写
绝对路径:从盘符开始的
相对路径:相对于当前项目的根目录
1.3 构造方法 创建File对象,只是将字符串封装,不考虑路径的真假。
File(String fileName)
File(String parent,String child); //可以将路径拆开成两个字符串,创建的时候会自动把两个连起来 new File("d:\\","a.txt");
File(File parent,String child); //用处同上,参数不同。 new File(new File("d:\\"),"c.txt")
1.4 方法
public String getAbsolutePath() //返回绝对路径
public String getPath() //返回构造方法中的路径;toString()调用的就是该方法
public String getName() //构造方法传递的结尾部分
public long length() //获取文件大小。以字节为单位。文件夹没有大小,返回0。如果文件不存在,返回0
public boolean exists() //是否存在
public boolean isDirectory() //是否是文件夹
public boolean isFile() //是否是文件(如果文件不存在返回false,上同)
public boolean createNewFile() //创建文件。创建了则返回true,只能创建文件;路径不存在会抛异常
public boolean mkdir() //创建单级文件夹。创建了则返回true,否则返回false;路径不存在返回false
public boolean mkdirs() //可创建单级或多级文件夹
public boolean delete() //删除文件或文件夹。文件夹中如果有内容,不会删除返回false。删除是从硬盘直接删除不走回收站
public String[] list() //遍历文件夹下,返回文件名string数组。若给出的路径不存在或者不是文件夹,会抛出空指针异常,下同
public File[] listFiles() //遍历文件夹下,返回File数组
2.文件过滤器
2.1 File类中有两个listFiles重载的方法,可以传递过滤器
File[] listFiles(FileFilter filter)
File[] listFiles(FilenameFilter filter)
2.2 java.io.FileFilter接口,用于抽象路径名(File对象)的过滤器
用于过滤文件
抽象方法:boolean accept(File pathname) pathname就是使用listFiles遍历得到的每一个文件对象
java.io.FilenameFilter接口
用于过滤文件名
抽象方法:boolean accept(File dir,String name) dir是构造方法包中被遍历的目录,name为遍历获取的文件名称
这两个过滤器接口没有实现类,需要自己写,并重写方法accept定义过滤规则
public class Demo01 {
public static void main(String[] args) {
File[] listFile1 = new File("D:\\搜狗高速下载").listFiles((pathname) -> pathname.isDirectory());
File[] listFile2 = new File("D:\\搜狗高速下载").listFiles((d, name) -> new File(d, name).isDirectory());
for (File temp : listFile2) {
System.out.println(temp.getName());
}
}
}
3.字节流 一切皆为字节 java.io
3.1 字节输出流:OutputStream,所有字节输出流最顶层的超类(abstract)
public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 o 开始输 出到此输出流。
public abstract void write(int b) :将指定的字节输出流。
3.2 文件字节输出流:FileOutputStream,把内存中数据写入到磁盘文件
FileOutputStream(String name) name写入数据的目的路径
FileOutputStream(File file)
FileOutputStream(String name,boolean append) append追加flag
FileOutputStream(File file,boolean append)
构造方法作用:创建一个对象;根据路径或文件创建一个空文件;将该对象指向创建的文件
try {
FileOutputStream fos = new FileOutputStream("01.txt"); //没有文件会自动创建新的
fos.write(65); //该方法会将该int对应ascii码的字符写入文件
fos.close();
byte[] bytes = { -65, -66, -67, 68, 69 };
fos.write(bytes); //如果写入的第一个字节是正数(0-127),那么显示的时候会查ascii码表;如果是负数,那么会取两个字节组成一个中文显示,查询系统默认码表
fos.write(bytes,1,2);
fos.write("你好".getBytes()); //通过获取字符串的bytes写入文件,看到的就是写入的
fos.write("\r\n".getBytes()); //换行。windows:\r\n Linux:/n mac:/r
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
3.3 字节输入流:FileInputStream
FileInputStream(String name)
FileInputStream(File file)
构造方法作用:创建一个对象;对象指向对应文件
FileInputStream fis = new FileInputStream("01.txt");
int len = 0;
while ((len = fis.read()) != -1) { //一次读取一个字节
System.out.println(len);
}
byte[] bytes = new byte[1024]; //一次读取多个字节
while ((len = fis.read(bytes)) != -1) { //一般定义成1024(1kb或者1024的整数倍)起到缓冲的作用,该方法返回的是每次读取到的字节个数
// System.out.println(Arrays.toString(bytes)); //查看的是字节int数组
System.out.println(new String(bytes)); //使用bytes创建String便于查看(String(byte[] bytes) / String(byte[] bytes,int offset,int length))
System.out.println(new String(bytes,0,len)); //只打印读取出来的长度。上面那句即是不够1024也会打印出1024长度的字符串
}
fis.close();
3.4 文件复制
FileInputStream fis = new FileInputStream("01.txt");
FileOutputStream fos = new FileOutputStream("02.txt");
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len); //加上len可以保证最后一次写入的长度是len,不然写入的是数组的大小1024,会导致复制的文件比源文件要大
}
fos.close();
fis.close();
3.5 字节流读取中文的问题
一个中文:GBK 占用2字节
UTF-8 占用3字节
字节读取是一个一个字节来读,故中文显示会出现乱码。此时需要用字符流(复制文件并不影响,只是影响显示)
4.字符流
4.1 字符输入流:java.io.Reader ,抽象类,所有字符输入流最顶层的超类
int read() 读取单个字符并返回
int read(char[] cbuf) 一次读入多个字符到数组
void close() 关闭流
4.2 文件字符输入流:FileReader extends InputStreamReader extends Reader 将文件以字符流的形式读入内存
FileReader(String fileName)
FileReader(File file)
构造方法作用:创建对象;将对象指向文件
FileReader fr = new FileReader("01.txt");
int len = 0;
while ((len = fr.read()) != -1) { //每次都会读取一个字符,故可以正常显示
System.out.println((char) len);
}
fr.close();
上述读取也可以改成读取字符数组:
char[] cs = new char[1024];
while ((len = fr.read(cs)) != -1) {
System.out.println(new String(cs, 0, len));
}
4.3 字符输出流:java.io.Writer,抽象类
void write(int c) 写入单个字符
void write(char[] cbuf)
abstract void write(char[] cbuf,int off,int len)
void write(String str) 写入字符串
void write(String str,int off,int len)
void flush() 刷新该流的缓冲
void close() 关闭流,需要先刷新
4.4 文件字符输出流:FileWriter extends OutputStreamWriter extends Writer 把内存字符数据写入文件
FileWriter(String fileName) //两个构造方法同样有续写开关:FileWriter(String fileName,boolean append)
FileWriter(File file)
构造方法作用:创建对象;根据构造方法传递的文件或路径创建文件;对象指向创建的文件
字符输出流使用步骤(同字节有区别):
1.创建FileWriter对象
2.使用write,把数据写入内存缓冲区(字符转换为字节的过程)
3.使用flush,把内存缓冲区中的数据刷新到文件中
4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
FileWriter fw = new FileWriter("01.txt");
fw.write(97);
fw.close(); //只有flush或者close后缓冲区的数据才会被写入文件
cha[] cs={'a','b','c','d'}
fw.write(cs,1,2);
fw.write("你好啊");
fw.write("你好啊",1,2); //换行写入的字符规则同文件字节输出流一样
5.处理流异常
jdk1.7之前,使用:
try{
}catch{
}finally{}
JDK7新特性:在try后面可以增加一个(),在括号中可以定义流对象,这个流对象就在整个try作用域有效,try中代码执行完毕会自动把流对象释放,不用写finally
try(FileInputStream fis=new FileInputStream("01.txt");
FileOutputStream fos=new FileOutputStream("02.txt"); ){
int len = 0;
while ((len = fis.read()) != -1) {
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
JDK9新特性:try前可以定义对象,在try后的()中可以直接引入流对象的名称,在try中执行完毕后,流也可以释放掉,不用finally
FileInputStream fis=new FileInputStream("01.txt");
FileOutputStream fos=new FileOutputStream("02.txt");
try(fis;fos){
int len = 0;
while ((len = fis.read()) != -1) {
fos.write(len);
}
}catch(IOException e){
System.out.println(e);
}
6.java.util.Properties集合 extends Hashtable<k,v> implements Map<k,v> 表示一个持久的属性集,可保存在流中或从流中读取。属性列表中每个键值都是字符串,是唯一一个与IO流相结合的集合
6.1 可以使用方法store保存集合到硬盘,使用load把文件中键值读取
Object setProperty(String key ,String value) 调用Hashtable中的put方法
String getProperty(String key) 获取key的value,相当于map中的get(key)
Set<String> stringPropertyNames() 返回键集,相当于map中的keySet
void store(OutputStream out,String comments) 字节输出流,不能写入中文;comments:注释,用来解释保存的文件是做什么用的,不能使用中文会乱码,默认Unicode,一般使用空字符串即可,下同
void store(Writer writer ,String comments) 字符输出流,可以写入中文
void load(InputStream inStream) 不可读取中文(存储键值对的文件中,键值间的连接符号可以用=,空格(其他符号);文件可以使用#进行注释;文件键值默认为字符串,不用再加引号)
void load(Reader reader) 可以读取中文
保存:
Properties prop = new Properties();
prop.setProperty("1", "good");
prop.setProperty("2", "好的");
prop.setProperty("3", "bad");
prop.setProperty("4", "坏的");
FileWriter fw = new FileWriter("prop.txt");
prop.store(fw, "save data");
读取:
Properties prop = new Properties();
prop.load(new FileReader("prop.txt")); //读入文件
Set<String> keySet = prop.stringPropertyNames(); //获取键值set
for (String key : keySet) {
System.out.println(key + "=" + prop.getProperty(key)); //遍历打印
}
7.缓冲流
7.1 java.io.BufferedOutputStream extends OutputStream 字节缓冲输出流
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int size) //out 字节输出流,可以传递FileOutputStream,缓冲流会给他增加一个缓冲区,提高效率;size 指定缓冲流内部缓冲区大小,不指定就默认
使用步骤:
1.创建FileOutputStream对象,构造方法中绑定输出的目的地
2.创建BufferedOutputStream对象,构造方法中传递FileOutputStream对象
3.使用BufferedOutputStream中的write,把数据写入到内部缓冲区
4.使用BufferedOutputStream中的flush,把内部缓冲区中的数据刷新到文件中
5.释放资源(会先调用flush,第4步可省略)
FileOutputStream fos = new FileOutputStream("01.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("AAAA".getBytes());
bos.close(); //缓冲流关闭会自动关闭字节流,可以不用再对fos进行关闭。下面的bis同理
7.2 java.io.BufferedInputStream extends InputStream 字节缓冲输入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size) //in 字节输入流,可以传递FileInputStream
使用步骤:
1.创建FileInputStream对象,构造方法绑定读取的数据源
2.创建BufferedInputStream对象,构造方法传递FileInputStream对象
3.使用FileInputStream对象的read,读取文件
4.释放资源
FileInputStream fis = new FileInputStream("02.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
int len = 0;
while ((len = bis.read()) != -1) {
System.out.println(len);
}
byte[] bytes = new byte[1024]; //存储每次读取的数据
len = 0; //记录每次读取的有效字节个数
while ((len = bis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, len));
}
bis.close(); //参bos,无需单独对fis做关闭
7.3 java.io.BufferedWriter extends Writer 字符缓冲输出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size) //out 字符输出流,可以传递FileWriter
特有的成员方法:
void newLine() //写入一个行分隔符。会根据不同的操作系统,获取不同的行分隔符
使用步骤:
1.创建字符缓冲输出流对象,构造方法中传递字符输出流
2.调用字符缓冲输出流中的write,写入数据到缓冲区
3.调用字符缓冲输出流中的flush,将缓冲区数据刷新到文件中
4.释放资源
BufferedWriter br = new BufferedWriter(new FileWriter("03.txt"));
for (int i = 0; i < 10; i++) {
br.write("好的");
br.newLine();
}
br.close();
7.4 java.io.BufferedReader 字符缓冲输入流
BufferedReader(Reader in)
BufferedReader(Reader in, int size) //in 字符输入流,可以传入FileReader,提高读取效率
特有的成员方法:
String readLine() 读取一个文本行(\r,\n或者\r\n即认为是一行;返回值不包含任何终止符,文件末尾返回null)
使用步骤:
1.创建字符缓冲输入流,构造方法中传递字符输入流
2.使用字符缓冲输入流中的read/readLine读取文本
3.释放资源
BufferedReader br = new BufferedReader(new FileReader("03.txt"));
String tempString;
while ((tempString = br.readLine()) != null) {
System.out.println(tempString);
}
br.close();
8.转换流
windows创建文件时,默认保存的编码是ANSI,也就是GBK。用FileReader读取时就会乱码
FileReader和FileWriter都只能使用ide默认的编码方式(UTF-8)
8.1 java.io.OutputStreamWriter extends Writer 是字符流通向字节流的桥梁,可使用指定的编码方式将要写入流中的字符编码成字节
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out, String charsetName) //out 字节输出流;charsetName 指定的编码,不区分大小写,不指定的话默认utf-8
使用步骤:
1.创建OutputStreamWriter对象,构造方法中传递字节输出流和编码表名称
2.使用OutputStreamWriter对象中的write,把字符转换为字节存储缓冲区
3.使用OutputStreamWriter中的flush,刷新
4.释放资源
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("03.txt"), "GBK");
osw.write("你好");
osw.flush();
osw.close();
8.2 java.io.InputStreamReader extends Reader 是字节流通向字符流的桥梁,可使用指定的编码方式将读取的字节解码为字符
InputStreamReader(InputStream in)
InputStreamReader(InputStream in, String charsetName) //in 字节输入流;charsetName 指定的编码,不区分大小写,不指定的话默认utf-8
使用步骤:
1.创建InputStreamReader对象,构造方法中传递字节输入流和编码表名称(编码应与文件编码相同,否则会乱码)
2.使用InputStreamReader对象中的read,读取文件
3.释放资源
InputStreamReader isr = new InputStreamReader(new FileInputStream("03.txt"), "gbk");
int len = 0;
while ((len = isr.read()) != -1) {
System.out.println((char) len);
}
9.序列化
9.1 java.io.ObjectOutputStream extends OutputStream 对象的序列化流,把对象以流的形式写入到文件中
ObjectOutputStream(OutputStream out) 创建写入指定OutputStream的ObjectOutputStream。out 字节输出流
特有方法:
void writeObject(Object obj)
使用步骤:
1.创建ObjectOutputStream对象,构造方法中传递字节输出流
2.使用ObjectOutputStream中的writeObject,把对象写入文件
3.释放资源
序列化和反序列化时,会抛出java.io.NotSerializableException没有序列化异常。类通过实现java.io.Serializable 接口以启用其序列化功能,未实现该接口将无法使用其任何状态序列化或反序列化。
Serializable接口也叫标记型接口,实现后会给类添加一个标记,进行序列化反序列化时会检测这个标记,有即可进行,没有就会抛出该异常
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("04.txt"));
oos.writeObject(new Person("大王", 19));// 抛出异常java.io.NotSerializableException //Person实现序列化接口
oos.close();
对多个对象进行读写序列化时,读的顺序应该和写入的顺序相同,否则会抛异常(待验证)
9.2 java.io.ObjectInputStream extends InputStream 对象的反序列化流,把文件中保存的对象以流的方式读取出来使用
ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
特有方法:
Object readObject()
使用步骤:
1.创建ObjectInputStream对象,构造方法中传递字节输入流
2.使用ObjectInputStream中的readObject读取保存的对象(类必须存在对应的class文件)
3.释放资源
4.使用对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("04.txt"));
Person pp = (Person) ois.readObject();
ois.close();
System.out.println(pp);
9.3 transient 瞬态关键字
static是静态关键字,静态优先于非静态加载到内存中,优先于对象进入到内存中,被其修饰的成员变量不能被序列化,因为序列化的都是对象(如果将9.1 9.2的Person中的某个变量定义为static,序列化反序列化都无法将该变量的值传入,得到的只是默认值)
transient修饰的成员变量,也不能序列化
private static int age;
private transient int age; //效果相同
9.4 编译器(javac.exe)将类编译生成class文件,如果类实现了序列化接口,就会根据类的定义,给class文件添加一个序列号serialVersionUID,序列化进入文件;
反序列化的时候,会使用class文件中的序列号和序列化生成的文件中的序列号比较,如果相同则反序列化成功,不同则会抛出InvalidClassException(比如序列化后修改了类中变量的定义,后面没有序列化就直接反序列化,就会抛出异常)
可以自己设置一个serialVersionUID,来保持永远不变,必须为static final long serialVersionUID
private static final long serialVersionUID=1L;
private String name;
private int age;
10.打印流 java.io.PrintStream extends OutputStream PrintStream只负责数据输出,不负责读取;永远不会抛出IOException;有特有的方法print和println
PrintStream(File file) 输出的目的地是一个文件
PrintStream(OutputStream out) 输出的目的地是一个字节输出流
PrintStream(String filename) 输出的目的地是一个文件路径
如果使用继承自父类的write方法写数据,那么查看数据的时候会查询编码表 97->a;如果使用自己特有的方法print println写数据,写的数据原样输出 97->97
PrintStream ps = new PrintStream("05.txt");
ps.write(97);
ps.println(97);
ps.close();
可以改变输出语句的目的地(打印流方向):输出语句默认在控制台输出,使用System.setOut方法可以切换 static void setOut(PrintStream out)
PrintStream out = new PrintStream("05.txt");
System.out.println("输出控制台");
System.setOut(out);
System.out.println("输出在文件中");
out.close();
DOWN 返回