一、File类
概述:文件和目录(文件夹)路径名的抽象表示
简单理解:在创建file对象时,需要传递一个路径,这个路径顶为到哪个文件或者文件夹上,我们的File就代表哪个对象
File file=new File(“E:\Idea\io\1.jpg”)
1.File的静态成员
static String pathSeparator:与系统有关的路径分隔符,为了方便,他被表示为一个字符
static String separator:与系统有关的默认名称分隔符,为了方便,他被表示为一个字符串
import java.io.File;
public class Demo01File {
public static void main(String[] args) {
file01();
file02();
}
/*
*
* 将来写代码如何正确编写一个路径用java代码
*
* */
private static void file02() {
String path1 = "D:\\Java\\JavaSE";
System.out.println(path1);
System.out.println("=========");
//要求代码写完,一次编写到处运行
String path2="D:"+File.separator+"Java"+File.separator+"JavaSe";
System.out.println(path2);
}
private static void file01() {
String pathSeparator = File.pathSeparator;
System.out.println(pathSeparator);
String separator = File.separator;
System.out.println(separator);
}
}
2.File的构造方法
File(String parent,String child)根据所填写的路径创建File对象
parent:父路径
child:子路径
File(File parent,String child)根据所填写的路径创建File对象
parent:父路径,是一个File对象
child:子路径
File(String pathname)所填写的路径创建File对象
pathname:直接指定路径
细节:
我们创建File对象的时候,传递的路径可以是不存在的,但是传递不存在的路径没啥意义
3.File的获取方法
String getAbsolutePath()->获取File的绝对路径->带盘符的路径
String getPath()->获取的是封装路径->new File对象的时候写的啥路径,获取的就是啥路径
String getName()->获取的是文件或者文件夹名称
long length()->获取的是文件的长度->文件的字节数
4.File的创建方法
boolean createNewFile()->创建文件
如果要创建的文件之前有,创建失败,返回false
如果要创建的文件之前没有,创建成功,返回true
boolean mkdir()->创建文件夹(目录)即可以创建多级文件夹,还可以创建单极文件夹
如果要创建的文件之前有,创建失败,返回false
如果要创建的文件之前没有,创建成功,返回true
5.File类的删除方法
boolean delete()->删除文件或者文件夹
注意:
如果删除文件,不走回收站
如果删除文件夹,必须是空文件夹,而且也不走回收站
6.File类的判断方法
boolean isDirectory()->判断是否为文件夹
boolean isFile()->判断是否为文件
boolean exists()->判断文件或者文件夹是否存在
7.File的遍历方法
String[] list()->遍历指定的文件夹,返回的是String数组
File[] listFiles()->遍历指定的文件夹,返回的是File数组->这个推荐使用
细节:listFiles方法底层还是list方法
调用list方法,遍历文件夹,返回一个String数组,遍历数组,将数组中的内容一个一个封装到File对象中,然后在将File对象放到File数组中
绝对路径:从盘符开始写的路径
例如:E:\\idea\\io\\1.txt
相对路径:不从盘符名开始写的路径
针对idea中写相对路径:
口诀: 哪个路径是参照路径,哪个路径就可以省略不写,剩下的就是在idea中写的相对路径写法在odea中参照路径其实就是当前project的绝对路径
二、字节流
1.IO流介绍以及输入输出以及流向的介绍
单词:Output输出
Input输入
Write:写数据
Read:读数据
IO流:
将一个设备上的数据传输到另一个设备上,称之为IO流技术
为啥要学IO流呢?
之前学了一个集合以及数组,可以保存数据,但是这两个都是临时存储的(代码运行完毕,集合和数组都会从内存中消失,从而数据就不存在了,所以集合和数组达不到永久保存的目的,我们希望咱们的数据永久保存起来,所以我们就可以将数据保存到硬盘上,此时我们就可以随时想拿到硬盘上的数据就随时拿,而且我们将来传输数据,必然要用到输入,输出动作。
IO流的流向_针对Se阶段的IO
输入流:将数据从硬盘上读到内存中 Input
输出流:从内存出发,将数据写到硬盘中 Output
要是从电脑和电脑之间数据传输,就是相对的
发数据一方:输出
接收数据一方:输入
IO流分类
字节流:万能流,一切皆字节
字节输出流:OutputStream 抽象类
字节输入流:InputStream 抽象类
字符流:专门操作文本文档
字符输出流:writer 抽象类
字符输入流:Reader 抽象类
2.OutputStream中子类[FileOutputStream]的介绍以及方法的简单介绍
概述:字节输出流,OutputStream是一个抽象类 子类:FileOutputStream
作用:往键盘上写数据
构造:
FileOutputStream(File file)
FileOutputStream(String name)
特点:指定的文件如果没有,输出流会自动创建
每执行一次,默认都会创建一个新的文件,覆盖老文件
方法:
void write(int b) 一次写一个字节void write(byte[] b) 一次写一个字节数组
void write(byte[] b,int off,int len) 一次写一个字节数组一部分
b:写的数组
off:从数组的哪个索引开始写
len:写多少个
void close()->关闭资源
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException{
// method01();
// method02();
// method03();
method04();
}
private static void method04() throws IOException{
FileOutputStream fos = new FileOutputStream("file\\1.txt",true);
fos.write("床前明月光\r\n".getBytes());
fos.write("床前明月光\r\n".getBytes());
fos.write("床前明月光\r\n".getBytes());
fos.write("床前明月光\r\n".getBytes());
fos.write("床前明月光\r\n".getBytes());
fos.close();
}
private static void method03() throws IOException{
FileOutputStream fos = new FileOutputStream("file\\1.txt");
byte[] bytes={97,98,99,100,101,102,103};
fos.write(bytes,0,2);
fos.close();
}
private static void method02() throws IOException {
FileOutputStream fos = new FileOutputStream("file\\1.txt");
byte[] bytes={97,98,99,100,101,102,103};
fos.write(bytes);
fos.close();
}
private static void method01() throws IOException {
FileOutputStream fos = new FileOutputStream("file\\1.txt");
fos.write(97);
}
}
字节流的续写追加:FileOutputStream(String name,boolean append) append:true->会实现续写追加,文件不覆盖了
换行:windows:\r\n->占两个字节 \n
Linux:\n
mac os:\r
3.读取-1的问题
每个文件末尾都会有一个“结束标记”,这个“结束标记”我们看不见,摸不着,而read()方法规定,如果读到了文件的结束标记,方法直接返回-1
三、字符流
1.字符输入流
- 注意:字节流是万能流,更侧重于文件复制,但是尽量不要边读边看
- 原因:UTF-8一个汉字占3个字节 GBK:一个中文占2个字节
- 如果按照字节读取,每次读取的字节没有构成一个汉字的字节数,就直接输出,汉字是显示不了的
- 解决:将文本文档中的内容,按照字符去操作
- 按照字符去操作编码也要一致,如果不一致,照样会乱码,按照字节流去操作即使编码一致,边读边看,也有可能乱码
2.FileReader的介绍以及使用
字符流是专门操作文本文档的,复制操作要用字节流
概述:字符输入流->Reader->是一个抽象类
子类:FileReader
作用:将文本文档中的内容读取到内存中来
构造:
FielReader(File file)
FileReader(String path)
方法:
Int read()->一次读取一个字符,返回的是读取字符对应的int值
Int read(char [] cbuf)->一次读取一个字符数组,返回的是读取个数
Int read(char[] ,int off,int len)->一次读取一个字符数组一部分。返回的是读取个数 cubf:读取的数组 off:从数组的哪个索引开始读 len:读多少个
Void close()->关闭资源
import java.io.FileInputStream;
public class Demo01FileReader {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("file\\1.txt");
byte[] bytes=new byte[3];
int len;
while ((len=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,len));
}
fis.close();
}
}
3.字符输出流(写数据)
概述:字符输出流->writer->抽象类
子类:Filewriter
作用:将数据写到文件中
构造:
FielWriter(File file)
FileWriter(String fileName)
FileWriter(String fileName,boolean append)->追加,续写
方法:
void write(int c)->一次写一个字符
void write(char[] cbuf)一次写一个字符数组
void write(char[] cbuf,int off,int len)一次写一个字符数组一部分
void write(String str)直接写一个字符串
void close()关流
注意:FileWriter底层自带一个缓冲区,我们写的数据会先保存到缓冲区,所以我们需要将缓冲区中的数据刷到文件中
FileWriter的刷新功能和关闭功能
Flush():将缓冲区中的数据刷到文件中,后续流对象还能继续使用
Close():先刷新后关闭,后续流对象不能使用了
import java.io.FileReader;
public class Demo02FileReader {
public static void main(String[] args) throws Exception{
//method01();
method02();
}
private static void method02() throws Exception{
FileReader fr = new FileReader("file\\1.txt");
char[] chars=new char[2];
int len;
while ((len=fr.read(chars))!=-1){
System.out.print(new String(chars,0,len));
}
fr.close();
}
private static void method01() throws Exception{
FileReader fr = new FileReader("file\\1.txt");
int len;
while ((len=fr.read())!=-1){
System.out.print((char) len);
}
fr.close();
}
}
四、IO流异常处理
格式:
try(IO对象){
可能出现异常的代码
}catch(异常类型 对象名){
处理异常
}
注意:以上格式处理IO异常,会自动关流
import java.io.FileWriter;
import java.io.IOException;
public class Demo01Exception {
public static void main(String[] args) {
FileWriter fw=null;
try {
fw = new FileWriter("file\\3.txt");
fw.write("你好");
fw.write("你");
}catch (Exception e){
e.printStackTrace();
}finally {
//如果fw不为null证明new出来了所以需要close相反不需要
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
五、字节缓冲流
为什么要学字节缓冲流?
之前所写的FileOutputStream,FileInputStream,FileReader,FileWriter这都叫基本类,其中FileInputStream和FileOutputStream的读写方法都是本地方法(方法声明上带native),本地方法是和系统以及硬盘打交道的,也就是说这两个对象的读和写都是在硬盘之间进行读写的,效率不高,缓冲流中底层带一个长度为8192的数组(缓冲区),此时读和写都是在内存中完成的(在缓冲区之间完成),内存中的读写效率非常高
使用之前需要将基本流包装成缓冲流,其实就new对象时,传递基本流
字节缓冲流
BUfferedOutputStream:字节缓冲输出流
构造:BUfferedOutputStream(InputStream in)
使用:和FileInputStream一样
import java.io.BufferedInputStream;
import java.io.FileInputStream;
public class Demo01BufferedInputStream {
public static void main(String[] args) throws Exception{
method01();
}
//用基本流复制文件
private static void method01()throws Exception {
long start=System.currentTimeMillis();
FileInputStream fis = new FileInputStream("buffered\\1.txt");
FileInputStream fos = new FileInputStream("buffered\\2.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedInputStream bos=new BufferedInputStream(fos);
//边读边写
int len;
while ((len=bis.read())!=-1){
// bos.write(len);
}
long end=System.currentTimeMillis();
System.out.println(end-start);
bis.close();
bos.close();
}
}
细节:
问题一:使用缓冲流的时候,为什么只需要关闭缓冲流,不用单独关闭基本流呢?
原因:缓冲流的close方法底层会自动关闭基本流
问题二:缓冲底层有数组(缓冲区),都是在内存之间进行读写,那么缓冲流读写的过程是啥样的呢?
注意:先依靠基本流将数据读取出来,然后交给缓冲流,由于缓冲流缓冲区是8192,所以每次读取8192个字节放到缓冲区,然后在将输入流缓冲区中的数据交给输出缓冲区,然后在利用基本流将数据写到硬盘上。那么在操作代码时len是干嘛的呢?主要时在两个缓冲区中倒腾数据,将输入流缓冲区中的数据读到,然后写到输出流缓冲区中,等待输出流缓冲区满了,在依靠基本流写到硬盘上如果输入流缓冲区中的数据读不到了,重新从硬盘上读8192个字节,进入到输入流缓冲区中,继续利用len在两个缓冲区中来回倒腾数据
六、字符缓冲流
1.字符缓冲输出流_BufferedWriter
构造:BufferedWriter(Writer w)
方法:用起来和FileWriter一样
特有方法:newLine()换行
import java.io.BufferedWriter;
import java.io.FileWriter;
public class Demo02BufferWriter {
public static void main(String[] args) throws Exception{
BufferedWriter bw = new BufferedWriter(new FileWriter("buffered\\1.txt", true));
bw.write("年底所代表的的");
bw.newLine();
bw.write("年底所表的的");
bw.newLine();
bw.write("年底所代的");
bw.newLine();
bw.close();
}
}
2.字符缓冲输入流_BufferedReader
构造:BufferedReader(Reader r)
方法:用法和FileReader一样
特有方法:String readLine()->一次读一行,如果读到结束标记,返回的时null
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo03BufferedReader {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new FileReader("buffered\\1.txt"));
/*String s = br.readLine();
System.out.println(s);
String s1 = br.readLine();
System.out.println(s1);
String s2 = br.readLine();
System.out.println(s2);
*/
//定义一个字符串接受读取的内容
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
br.close();
}
}
七、字符编码
计算机中存储的信息都是用二进制表示的,而我们在屏幕上看到的数组、英文、标点符号、汉字等字符是二进制数转换之后的结果,按照某种规则,将字符存储到计算机中,称之为编码,反之,将存储在计算机中的二进制数按照某种规则则解析显示出来,称之为解码。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确1的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。
1.字符集
字符集:也叫编码表,是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符、数组等
计算机要准确的存储和识别各种各样字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCLL字符集、GBK字符集、Unicode字符集等
八、转换流
1.转换流_InputStreamReader
字节流读取中文在编码一致的情况,也不要边读边看,因为如果字节读不准,读不全,输出的内容可能会出现乱码,所以我们学了字符流,字符流读取文本文档中的内容如果编码一致,就不会出现乱码问题了。但是如果编码不一致,字符流读取的文本文档中的内容也有可能出现乱码
概述:是字节流通向字符流的桥梁->读数据
构造:
InputStreamReader(InputStreamReader in,String charsetName)
charsetName :指定编码,不区分大小写
作用:可以直接指定编码,按照指定的编码去读内容
用法:和fileReader的用法一样
2.转换流-OutputStreamWriter
概述:是字符流通向字节流的桥梁
构造:
OutputStreamWriter(OutputStreamWriter out,String charsetName)
作用:按照指定的编码规则去存数据
用法:和fileWriter用法一样
九、序列化流
1.序列化流和反序列化流介绍
作用:读写对象
两个对象:
ObjectOutputStream->序列化流->写对象
ObjectInputStream->反序列化流->读对象
注意:我们将对象序列化到文件中,我们打开文件看不懂,这就对了,很多时候我们操作的数据不能随便让别人看懂,不然别人就随意改动了,我们只需要将这些看不懂的内容成功读回来即可
应用场景:比如玩游戏会对英雄存档,那么退出的时候英雄变成对象,将人物的属性变成对象的成员变量值,然后存到文件中,再次打开游戏直接从文件中将这些人物对象以及对象中的属性还原
2.序列化流_ObjectOutPutStream
作用:写对象
构造:ObjectOutputStream(OutputStream out)
方法:writeObject(Object obj)->写对象
注意:想要将对象序列化到文件中
3.反序列化_ObjectInputStrream
作用:读对象
构造:ObjectInputStream(InputStream in)
方法:Object readObject()
不想被序列化操作
Transient
import java.io.Serializable;
public class Person implements Serializable {
public static final long serialVersionUID=42L;
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Demo01 {
public static void main(String[] args)throws Exception {
// write();
read();
}
//反序列化
private static void read() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("buffered\\person.txt"));
Person person= (Person)ois.readObject();
System.out.println(person);
ois.close();
}
//序列化
private static void write() throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("buffered\\person.txt"));
Person p1 = new Person("名", 18);
oos.writeObject(p1);
oos.close();
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class Demo02 {
public static void main(String[] args)throws Exception {
// write();
read();
}
//反序列化
private static void read() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("buffered\\person.txt"));
/*for (int i = 0; i <3; i++) {
Person person= (Person)ois.readObject();
System.out.println(person);
}*/
//将集合反序列化即可
ArrayList<Person> list= (ArrayList<Person>) ois.readObject();
for (Person person : list) {
System.out.println(person);
}
ois.close();
}
//序列化
private static void write() throws Exception{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("buffered\\person.txt"));
//创建一个集合,存储多个Person对象
ArrayList<Person> list = new ArrayList<>();
Person p1 = new Person("名", 18);
Person p2 = new Person("怡", 18);
Person p3 = new Person("杨", 18);
//存储到集合中
list.add(p1);
list.add(p2);
list.add(p3);
oos.writeObject(list);
oos.close();
}
}
十、打印流
1.打印流PrintStream打印流基本使用
构造:PrintStream(String fileName)
方法:
printLn():原样输出,自带换行效果
print():原样输出,不带换行效果
import java.io.PrintStream;
public class Demo01PrintStream {
public static void main(String[] args) throws Exception {
//打印流
PrintStream ps = new PrintStream("buffered\\printstream.txt");
ps.println("dddaa电脑手机");
ps.println("dd电脑手机");
ps.println("da电脑手机");
ps.close();
}
}
改变流向:
什么叫做改变流向:System.out.printLn()->本身是输出到控制台上
改变流向:可以让输出语句从控制台上输出改变成往指定文件中输出
方法:System中的方法
static void setOut(PrintStream out)->改变流向->让输出语句从控制台输出转移到指定文件中
import java.io.PrintStream;
public class Demo02PrintStream {
public static void main(String[] args) throws Exception {
//打印流
PrintStream ps = new PrintStream("buffered\\printstream.txt");
//改变流向
System.setOut(ps);
System.out.println("出现错误2点");
System.out.println("结尾异常");
System.out.println("循环反序列次数不对");
ps.close();
}
}
使用场景:可以将输出的内容以及详细信息放到日志文件中,永久保存
以后我们希望将输出的内容永久保存,但是输出语句会将结果输出到控制台上,控制台是临时显示,如果有新的程序运行,新程序的运行结果会覆盖之前的结果,这样无法达到永久保存,到时候我们想看看之前的运行结果信息就看不到了,所以我们需要将输出的结果保存到日志文件中,就可以使用setOut改变流向
2.PrintStream打印流完成续写
PrintStream(OutputStream out)->可以依靠OutputStream的续写功能完成打印流续写
import java.io.FileOutputStream;
import java.io.PrintStream;
public class Demo03PrintStream {
public static void main(String[] args) throws Exception {
//打印流
PrintStream ps = new PrintStream(new FileOutputStream("buffered\\printstream.txt",true));
//改变流向
System.setOut(ps);
System.out.println("出现错误2点");
System.out.println("结尾异常");
System.out.println("循环反序列次数不对");
ps.close();
}
}
十一、Properties集合(Properties结合IO流使用方法)
使用场景:配合配置文件使用
注意:将来我们不能将很多的硬数据放到源码中,比如用户名和密码这些数据,因为将来我们有可能换用户名或者密码,如果一换,我们就需要去源码中直接修改,将来我们的类和类之间都有联系有可能牵一发而动全身,所以我们需要将这些数据提取出来,放到文件中,改的时候直接去文件中改,源码不需要改动
创建配置文件:
- 在模块下右键->file 取名为xxxx.properties
- 在文件中写配置数据
Key和value都是key=value形式
Key和value都是string的但是不要加双引号
每个键值对写完之后,需要换行在写下一对
键值对之间最好不要有空格(空格可以有但是不建议写)
键值对中建议不要使用中文(中文可以有,但是直接读取会乱码,需要转换流转码)
Jdbc.username=root
Jdbc.password=1234
import java.util.Properties;
import java.util.Set;
public class Demo01Perperties {
public static void main(String[] args) {
Properties properties = new Properties();
properties.setProperty("username","root");
properties.setProperty("password","1234");
Set<String> set = properties.stringPropertyNames();
for (String key : set) {
System.out.println(properties.getProperty(key));
}
}
}
import java.io.FileInputStream;
import java.util.Properties;
import java.util.Set;
public class Demo02Perperties {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
FileInputStream fis = new FileInputStream("buffered\\jdbc.properties");
properties.load(fis);
Set<String> set = properties.stringPropertyNames();
for (String key : set) {
System.out.println(key+"..."+properties.getProperty(key));
}
}
}