目录
文件(File):
文件就是保存数据的地方,如word,excel,txt等。
文件(IO)流:
文件在程序中是以流的形式来操作的。
流:数据在数据源和程序之间经历的路径。
输入流(input):数据从数据源到程序的路径。
输出流(output):数据从程序到数据源的路径。
以内存为参考点,从其他位置输入到内存就是输入流,从内存输出到其他位置就是输出流。
常用的文件操作:
1:创建文件:
public class FileTest1 {
public static void main(String[] args) {
/*String filePath="D:\\TestFile\\Rider.txt";
creatFile1(filePath);*/
/*File fatherFile=new File("D:\\TestFile\\");
String childFile="Rider2.txt";
creatFile2(fatherFile,childFile);*/
String fatherFile="D:/TestFile/";
String childFile="Rider3.txt";
creatFile3(fatherFile,childFile);
}
public static void creatFile1(String s){
File file=new File(s);//在内存中
try {
file.createNewFile();//创建在磁盘/硬盘里
System.out.println("创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void creatFile2(File fatherFile,String childFile){
File file=new File(fatherFile,childFile);
try {
file.createNewFile();
System.out.println("创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void creatFile3(String fatherFile,String childFile){
File file=new File(fatherFile,childFile);
try {
file.createNewFile();
System.out.println("创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2:常用文件方法:
File file=new File("D:\\TestFile\\Rider.txt");
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
System.out.println(file.getParent());
System.out.println(file.length());
System.out.println(file.exists());//是否存在
System.out.println(file.isFile());//是不是一个文件
System.out.println(file.isDirectory());//是不是一个目录
3:文件(和目录)常用的操作:
public class FileTest2 {
public static void main(String[] args) {
String filePath="D:\\TestFile\\2";
createDirectory(filePath);
}
//删除文件或者目录
public static void DeleteFile(String filePath){
File file=new File(filePath);
if(file.exists()){
if(file.delete()){
System.out.println("文件删除成功");
}else {
System.out.println("删除失败!");
}
}else {
System.out.println("文件不存在!");
}
}
//创建目录
/*
* boolean mkdir() 创建由此抽象路径名命名的目录。
* boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录。多级目录
* */
public static void createDirectory(String filePath){
File file=new File(filePath);
if(file.exists()){
System.out.println("该文件已经存在!");
}else {
if (file.mkdirs()){
System.out.println("创建成功!");
}else {
System.out.println("创建失败!");
}
}
}
}
IO流分类:
1:按操作数据单位不同分为:字节流(1字节(byte)等于8bit),字符流(按字符(char),Java中一个字符等于2字节)。
2:按数据流的流向不同分为:输入流,输出流。
3:按流的角色不同分为:节点流,处理流/包装流。
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
①:Java的IO流有40多个类,基本上都是在如上四个抽象基类派生的。
②:由这四个类派生出来的子类名称以父类名作为子类名的后缀名。
③:如果要使用必须使用这四个类的子类,因为这四个类是抽象类。
字节流:
InputStream(字节输入流):
常用子类:
1:FileInputStream:文件输入流
2:BufferedInputStream:缓存字节输入流(直接父类是:FilterInputStream)
3:ObjectInputStream:对象字节输入流
FileInputStream(文件字节输入流):
public class FileInputStreamTest {
public static void main(String[] args) {
String filePath="D:\\TestFile\\song.txt";
readFile2(filePath);
}
/*
* public int read()
throws IOException从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。
Specified by:
read在 InputStream
结果:
数据的下一个字节,如果达到文件的末尾, -1 。
异常:
IOException - 如果发生I / O错误。
* */
public static void readFile1(String filePath){
int readData=0;//存储读取的字节数据
FileInputStream fileInputStream = null;
File file=new File(filePath);
if(file.exists()){
try {
fileInputStream=new FileInputStream(filePath);
while((readData=fileInputStream.read())!=-1){//如果达到文件的末尾,read==-1 。
System.out.print((char)readData);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
System.out.println("文件不存在!!");
}
}
/*
* public int read(byte[] b)
throws IOException从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。
重写:
read在 InputStream类
参数
b - 读取数据的缓冲区。
结果
读入缓冲区的总字节数,如果没有更多的数据,因为文件的结尾已经到达, -1 。
异常
IOException - 如果发生I / O错误。
* */
public static void readFile2(String filePath){
int readLen=0;//存储读取的字节数据
byte[] bytes=new byte[3];//一次读取3个字节(1个中文就是3个字节)
FileInputStream fileInputStream = null;
File file=new File(filePath);
if(file.exists()){
try {
fileInputStream=new FileInputStream(filePath);
while((readLen=fileInputStream.read(bytes))!=-1){//如果达到文件的末尾,read==-1 。
System.out.print(new String(bytes,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
System.out.println("文件不存在!!");
}
}
}
FileOutputStream(文件字节输出流):
public class FileOutputStreamTest {
public static void main(String[] args) {
String filePath="D:\\TestFile\\Rider4.txt";
String txt="你好";
writeFile(filePath,txt);
}
public static void writeFile(String filePath,String txt){
FileOutputStream fileOutputStream=null;
File file=new File(filePath);
if(file.exists()){
try {
fileOutputStream=new FileOutputStream(filePath,true);//如果不加true就是覆盖原内容
fileOutputStream.write(txt.getBytes());//txt字符串转为字符数组(Java中一个字符为2字节)
fileOutputStream.write(txt.getBytes());//同一个流不会覆盖
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}else{
try {
file.createNewFile();
fileOutputStream=new FileOutputStream(filePath,true);//加了true就是追加内容
fileOutputStream.write(txt.getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件复制(FileCopy-字节流):
public class FileCopyTest {
public static void main(String[] args) {
String oldfilePath="D:\\TestFile\\Rider4.txt";
String newfilePath="D:\\TestFile\\Rider5.txt";
FileCopy(oldfilePath,newfilePath);
}
public static void FileCopy(String oldfilePath,String newfilePath){
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
File oldfile=new File(oldfilePath);
File newfile=new File(newfilePath);
if (oldfile.exists()){
if(newfile.exists()){
try {
fileInputStream=new FileInputStream(oldfilePath);
fileOutputStream=new FileOutputStream(newfilePath);
//fileOutputStream=new FileOutputStream(newfilePath,true);//加了true就是追加复制内容,而不是覆盖复制内容
byte[] bytes=new byte[1024];//提高读取效率
int readLen=0;
while ((readLen=fileInputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,readLen);
}
System.out.println("Copy成功!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}else {
try {
newfile.createNewFile();
fileInputStream=new FileInputStream(oldfilePath);
fileOutputStream=new FileOutputStream(newfilePath);
//fileOutputStream=new FileOutputStream(newfilePath,true);//加了true就是追加复制内容,而不是覆盖复制内容
byte[] bytes=new byte[1024];//提高读取效率
int readLen=0;
while ((readLen=fileInputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,readLen);
}
System.out.println("Copy成功!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}else{
System.out.println("文件不存在!!!");
}
}
}
字符流:
FileReader(文件字符输入流):
继承自InputStreamReader(InputStreamReader继承自Reader)。
public class FileReaderTest {
public static void main(String[] args) {
String filePath="D:\\TestFile\\song.txt";
Reader_File(filePath);
}
public static void Reader_File(String filePath){
FileReader fileReader=null;
char[] chars=new char[1024];
int charLen=0;
File file=new File(filePath);
if (file.exists()){
try {
fileReader=new FileReader(filePath);
while ((charLen=fileReader.read(chars))!=-1){
System.out.print(new String(chars,0,charLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileReader!=null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}else{
System.out.println("文件不存在!");
}
}
}
FileWrite(文件字符输出流):
FileWriter一定要关闭流,或者flush刷新,才能真正的把数据写入文件。所以养成好习惯,不管什么流用完都close一下。
public class FileWriterTest {
public static void main(String[] args) {
String filePath="D:\\TestFile\\Rider4.txt";
String txt="你好";
Writer_File(filePath,txt);
}
public static void Writer_File(String filePath,String txt){
FileWriter fileWriter=null;
File file=new File(filePath);
if(file.exists()){
try {
fileWriter=new FileWriter(filePath,true);
fileWriter.write(txt.toCharArray());
} catch (IOException e) {
e.printStackTrace();
} finally {
//FileWriter一定要关闭流,或者flush刷新,才能真正的把数据写入文件
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
try {
file.createNewFile();
fileWriter=new FileWriter(filePath,true);
fileWriter.write(txt);
} catch (IOException e) {
e.printStackTrace();
} finally {
//FileWriter一定要关闭流,或者flush刷新,才能真正的把数据写入文件
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
节点流和处理流:
基本介绍:
1:节点流:节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter。
2:处理流:也叫包装流,是“连接”在已经存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader,BufferedWriter。
区别和联系:
1:节点流是底层流/低级流,直接根数据源连接。
2:处理流(包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连接。
3:处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
处理流的功能主要体现:
1:性能高,主要以增加缓冲的方式来提高输入输出的效率。
2:操作便捷,处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便。
3:关闭处理流时,只需要关闭外层流即可。
处理流:
BufferedReader(缓冲的字符输入流):
public class BufferedReaderTest {
public static void main(String[] args) {
String filePath="D:\\IDEA项目目录\\Ridersong\\src\\main\\java\\HSP\\IO\\FileTest1.java";
Reader_Test(filePath);
}
public static void Reader_Test(String filePath){
BufferedReader bufferedReader=null;
String line;
File file=new File(filePath);
if(file.exists()){
try {
bufferedReader=new BufferedReader(new FileReader(filePath));
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bufferedReader.close();//其实它还是去关闭底层的FileReader
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
System.out.println("文件不存在!");
}
}
}
BufferedWriter(缓冲的字符输出流):
public class BufferedWriterTest {
public static void main(String[] args) throws IOException{
String filePath="D:\\TestFile\\Rider4.txt";
String txt="你好";
Writer_Test(filePath,txt);
}
public static void Writer_Test(String filePath,String txt) throws IOException {
File file=new File(filePath);
if (file.exists()){
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write(txt);
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.close();
}else{
file.createNewFile();
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write(txt);
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.close();
}
}
}
文件复制(FileCopy-缓冲的字符流):
public class BufferedFileCopyTest {
public static void main(String[] args) throws IOException {
String oldfilePath="D:\\TestFile\\Rider4.txt";
String newfilePath="D:\\TestFile\\Rider5.txt";
Copy_Test(oldfilePath,newfilePath);
//字符流不要去操作二进制文件,会造成文件损坏
//常见的二进制文件有可执行程序、图形、图像、声音、word、PDF等等。
}
public static void Copy_Test(String oldfilePath,String newfilePath) throws IOException{
BufferedReader bufferedReader=new BufferedReader(new FileReader(oldfilePath));
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter(newfilePath));
File oldfile=new File(oldfilePath);
File newfile=new File(newfilePath);
String line;
if(oldfile.exists()){
if(newfile.exists()){
while ((line=bufferedReader.readLine())!=null){
//readLine读取一行,但不会读取换行符
bufferedWriter.write(line);
//必须插入一个换行符不然,复制过后就成了一行
bufferedWriter.newLine();
}
System.out.println("Copy成功!");
bufferedReader.close();
bufferedWriter.close();
}else{
newfile.createNewFile();
while ((line=bufferedReader.readLine())!=null){
//readLine读取一行,但不会读取换行符
bufferedWriter.write(line);
//必须插入一个换行符不然,复制过后就成了一行
bufferedWriter.newLine();
}
System.out.println("Copy成功!");
bufferedReader.close();
bufferedWriter.close();
}
}else {
System.out.println("要复制的文件不存在!!");
}
}
}
文件复制(FileCopy-缓冲的字节流):
public class BufferedFileCopyTest_byte {
public static void main(String[] args) throws IOException{
String oldfilePath="D:\\TestFile\\Rider4.txt";
String newfilePath="D:\\TestFile\\Rider5.txt";
Copy_Test(oldfilePath,newfilePath);
}
public static void Copy_Test(String oldfilePath,String newfilePath) throws IOException {
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(oldfilePath));
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(newfilePath));
File oldfile=new File(oldfilePath);
File newfile=new File(newfilePath);
byte[] bytes=new byte[1024];
int byteLen=0;
if(oldfile.exists()){
if(newfile.exists()){
while ((byteLen=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,byteLen);
}
System.out.println("Copy成功!");
bufferedInputStream.close();
bufferedOutputStream.close();
}else{
newfile.createNewFile();
while ((byteLen=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,byteLen);
}
System.out.println("Copy成功!");
bufferedInputStream.close();
bufferedOutputStream.close();
}
}else {
System.out.println("要复制的文件不存在!!");
}
}
}
对象处理流:
能够将基本数据类型或者对象进行序列化和反序列化操作。
序列化和反序列化:
1:序列化就是在保存数据时,保存数据的值和数据类型。
2:反序列化就是恢复数据时,恢复数据的值和数据类型。
3:需要让某个对象支持序列化机制,则必须让其类是可序列化的,可实现以下两个接口之一:Serializable
是标记接口,Externalizable
该接口有方法需要实现。所以一般实现Serializable
。
注意事项:
1:读写顺序要一致。
2:要求实现序列化或反序列化对象,需要实现Serializable接口。
3:序列化的类中建议添加SerialVersionUID(序列化的版本号),为了提高版本兼容性。
4:序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员。
5:序列化对象时,要求里面属性的类型也需要实现序列化接口。
6:序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化。
ObjectOutPutStream(对象输出流):
public class ObjectOutputStreamTest {
public static void main(String[] args) throws IOException {
//序列化后,保存的文件格式,不是文本,而是按照它本身的格式
String filePath="D:\\TestFile\\song.txt";
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到filePath
objectOutputStream.writeInt(100);//int-->Integer-->Number-->实现了Serializable
objectOutputStream.writeBoolean(true);
objectOutputStream.writeChar('A');
objectOutputStream.writeDouble(9.9);
objectOutputStream.writeUTF("是个人");
//序列化对象
objectOutputStream.writeObject(new Dog("邓亮",22));
objectOutputStream.close();
System.out.println("序列化数据保存完毕!");
}
}
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
ObjectInputStream(对象输入流):
public class ObjectInputStreamTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath="D:\\TestFile\\song.txt";
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(filePath));
//读取(反序列化)的顺序需要与保存数据(序列化)的顺序一致
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readChar());
System.out.println(objectInputStream.readDouble());
System.out.println(objectInputStream.readUTF());
//dog编译类型是Object,dog的运行类型是Dog
Object dog=objectInputStream.readObject();
System.out.println("运行类型:"+dog.getClass());
System.out.println("dog信息:"+dog);
Dog dog1=(Dog)dog;
System.out.println(dog1.getName());
objectInputStream.close();
}
}
标准输入输出流:
类型 | 默认设备 | |
---|---|---|
System.in标准输入 | InputStream | 键盘 |
System.out标准输出 | PrintStream | 显示器 |
System.in编译类型是InputStream,运行类型是BufferedInputStream。
System.out编译类型是PrintStream,运行类型是PrintStream。
转换流:
1:InputStreamReader:Reader的子类,可以将InputStream包装(转换)成Reader。
2:OutputStreamWriter:Writer的子类,可以将OutputStream包装(转换)成Writer。
3:当处理纯文本数据时,如果使用字符流会效率更高,并且可以有效解决中文乱码的问题,所以建议将字节流转换为字符流。
4:可以在使用时指定编码格式(utf-8,gbk,gb2321,ISO08859-1等等)。
InputStreamReader(输入转换):
public class InputStreamReaderTest {
public static void main(String[] args) throws IOException {
String filePath="D:\\TestFile\\Rider4.txt";
InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream(filePath),"utf-8");
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
//2合1
//BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"utf-8"));
String s=null;
while((s=bufferedReader.readLine())!=null){
System.out.println(s);
}
bufferedReader.close();
}
}
OutputStreamWriter(输出转换):
public class OutputStreamWriterTest {
public static void main(String[] args) throws IOException {
String filePath="D:\\TestFile\\Rider4.txt";
BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath,true),"utf-8"));
bufferedWriter.write("你好");
bufferedWriter.close();
}
}
打印流:
PrintStream(字节打印流):
public class PrintStreamTest {
public static void main(String[] args) throws IOException {
PrintStream out=System.out;
out.print("sjj");
//print底层使用的是write方法,所以我们可以直接调用write进行打印/输出
out.write("SJJ".getBytes());
//可以修改打印流输出的位置/设备
System.setOut(new PrintStream("D:\\TestFile\\Rider.txt"));
System.out.println("你好!");
out.close();
}
}
PrintWriter(字符打印流):
public class PrintWriterTest {
public static void main(String[] args) throws IOException {
//PrintWriter printWriter=new PrintWriter(System.out);//在控制面版输出
PrintWriter printWriter=new PrintWriter(new FileWriter("D:\\TestFile\\Rider2.txt",true));//在指定文件输出
printWriter.print("你好!");
printWriter.close();
}
}
Properties类:
定义:
1:后缀properties是一种属性文件。
2:这种文件以key=value格式存储内容。
3:一般这个文件作为一些参数的存储,代码就可以灵活一点。
4:通俗点讲就相当于定义一个变量,在这个文件里面定义这些变量的值,在程序里面可以调用这些变量,好处就是,如果程序中的参数值需要变动,直接来改这个.property文件就可以了,不用在去修改源代码。
常规读取properties文件的一种方法:
public class PropertiesTest {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader=new BufferedReader(new FileReader("src/main/java/HSP/IO/mysql.properties"));
String line="";
while ((line=bufferedReader.readLine())!=null){
String[] str=line.split("=");
System.out.println(str[0]+" 的值是:"+str[1]);
}
bufferedReader.close();
}
}
Propertirs类的常见方法:
public class PropertiesTest2 {
public static void main(String[] args) throws IOException {
Properties properties=new Properties();
properties.load(new FileReader("src/main/java/HSP/IO/mysql.properties"));
properties.list(System.out);
String user=properties.getProperty("user");
String pwd=properties.getProperty("pwd");
System.out.println(user+"\t"+pwd);
properties.setProperty("charset","utf-8");
properties.setProperty("port","3306");
properties.store(new FileOutputStream("src/main/java/HSP/IO/mysql.properties",true),null);
}
}