File类实现了Serializable与Comparable接口
new File(String pathname)//根据路径构建一个File对象
new File(File parent,String pathname)//根据父目录文件+子路径构建一个File对象
new File(String parent,Sting child)//根据父路径+子路径构建一个File对象
new File (URI uri)//通过将给定的 file:
URI 转换为一个抽象路径名来创建一个新的 File
实例。
public static void main(String[] args) throws IOException, URISyntaxException { File file1=new File("d:/news1.txt"); File file2=new File("d:\\","news2.txt"); File file3=new File("d:\\"); File file4=new File(file3,"news3.txt"); URI uri=new URI("file:///d:/news4.txt"); File file5= new File(uri); //上面的file1、file2..等 只是在java中的一个对象 //只有执行了 createNewFile()方法,才会真正在磁盘中创建该文件 if(file1.createNewFile()&&file2.createNewFile()&&file4.createNewFile()&&file5.createNewFile()){ System.out.println("文件创建成功!"); }else { System.out.println("文件创建失败!"); } }
File对象常用的一些方法
流的分类
字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer
字节输入流(InputStream)常用的子类
FileInputStream
/** * 单个字节读取效率低 */ public void read01() { String path="d:\\news1.txt"; FileInputStream fileInputStream=null; try { fileInputStream=new FileInputStream(path); int read = 0; while ((read=fileInputStream.read())!=-1){ System.out.print((char) read); } } catch (IOException e) { e.printStackTrace(); }finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } public void read2(){ String path="d:\\news1.txt"; FileInputStream fileInputStream=null; //定义字节数组 byte[] buf=new byte[8]; try { fileInputStream=new FileInputStream(path); int readLen= 0; //fileInputStream.read(buf) 如果读取正常返回实际读取的字节数 每次最多读8字节 //如果返回-1,表示读取完毕 while ((readLen=fileInputStream.read(buf))!=-1){ System.out.print(new String(buf,0,readLen)); } } catch (IOException e) { e.printStackTrace(); }finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
FileOutPutStream
public class OutPutStream_ { public static void main(String[] args) { new OutPutStream_().writeFile(); } public void writeFile(){ String filePath="d:\\news.txt"; FileOutputStream fos=null; try { //若没有该文件,则会自动创建 fos=new FileOutputStream(filePath); /** * 1、new FileOutputStream(filePath);这种创建方式,当写入内容时,会覆盖其内容 * 2、new FileOutputStream(filePath,true);这种方式创建,当写入内容时,会以追加的方式,不会覆盖原内容 */ //写入一个字节 fos.write('a'); String str="wanna"; //将字符串转化为字符数组 str.getBytes() fos.write(str.getBytes()); /** * write(byte[] b, int off, int len) * 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 */ fos.write(str.getBytes(),0,3);//截取前三个字节写入 } catch (IOException e) { e.printStackTrace(); } finally { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
两者结合使用 拷贝文件
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class FileCopy { public static void main(String[] args) { FileInputStream fis=null; FileOutputStream fos=null; String filePath="d:\\a.jpg"; String destFilePath="c:\\a.jpg"; byte[] bytes=new byte[1024]; int readLen=0; try { fis=new FileInputStream(filePath); fos=new FileOutputStream(destFilePath); while ((readLen=fis.read(bytes))!=-1){ fos.write(bytes,0,readLen);//一定要使用这个方法 } System.out.println("拷贝完成!"); } catch (Exception e) { e.printStackTrace(); }finally { try { if (fis != null) { fis.close(); } if (fos != null) { fos.close(); } }catch (IOException e){ e.printStackTrace(); } } } }
FileReader与FileWriter
FileReader与FileWriter都是字符流,按照字符操作IO
FileReader
import java.io.FileReader; import java.io.IOException; public class FileReader_ { public void reader01(){ FileReader fileReader=null; try { fileReader=new FileReader("d:\\news.txt"); int data=0; while ((data=fileReader.read())!=-1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } public void reader02(){ FileReader fileReader=null; try { fileReader=new FileReader("d:\\news.txt"); int data=0; char[] chars=new char[5]; while ((data=fileReader.read(chars))!=-1) { System.out.print(new String(chars,0,data)); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new FileReader_().reader02(); } }
FileWriter
import java.io.FileWriter; import java.io.IOException; public class FileWriter_ { public void Writer01(){ String filePath="d:\\news.txt"; FileWriter fw=null; try { fw=new FileWriter(filePath); /** * * void write(char[] cbuf, int off, int len) * 写入字符数组的某一部分。 * void write(int c) * 写入单个字符。 * void write(String str, int off, int len) * 写入字符串的某一部分。 */ String str="你好这是void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。\n"; fw.write(str.toCharArray(),0,20); fw.write(77); fw.write('o'); fw.write("\n这是FileWriter......"); } catch (IOException e) { e.printStackTrace(); } finally { try { /** * 对于FileWriter,一定要关闭或者刷新流,才能将数据写入文件!!!! * flush()与close()在底层实现上都掉用了writeBytes() 才将数据写入文件 */ fw.flush(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new FileWriter_().Writer01(); } }
基本介绍
1.节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter(对文件读写)等。还有一些是对管道、数组等进行读写操作。
2.处理流也叫包装流是连接已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter。
两者的区别与联系:
- 节点流是底层流/低级流,直接和数据源相连
- 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法完成输入输出。
- 处理流(也叫包装流)是对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连。
BufferedReader与BufferedWriter属于字符流,按照字符来读取数据。所以不适合读取二进制文件。
BufferedReader
package Reader_; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class BufferedReader_ { public static void main(String[] args) { String filePath="d:\\news.txt"; BufferedReader bufferedReader=null; try { bufferedReader = new BufferedReader(new FileReader(filePath)); String line;//按行读取 /** * bufferedReader.readLine 按行读取 * 当返回为null时读取完毕 */ ; while (( line=bufferedReader.readLine())!=null){ System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { /** *这里不需要关闭 FileReader *只需要关闭外层包装流,它会调用你穿进来的流的close()方法 */ bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
BufferedWriter
package Writer_; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class BufferedWriter_ { public static void main(String[] args) throws IOException { String filePath="d:\\news1.txt"; /** * new FileWriter(filePath,true) 是以追加的方式进行写入 * new FileWriter(filePath)是以覆盖的方式写入 */ BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath)); bufferedWriter.write("祝大家百万年薪!!!"); bufferedWriter.newLine();//插入一个和系统相关的换行 bufferedWriter.write("我们都是打工人!!!"); /** * 这里关闭外层包装流即可,它会在底层调用 你传进来的流的close方法 */ // bufferedWriter.flush(); bufferedWriter.close(); } }
使用BufferedWriter与BufferedReader拷贝文件
package Copy; import java.io.*; public class BufferedCopy_ { public static void main(String[] args) throws IOException { String srcPath="d:\\news.txt"; String destPath="d:\\news2.txt"; BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destPath)); BufferedReader bufferedReader=new BufferedReader(new FileReader(srcPath)); String line=null; while ((line=bufferedReader.readLine())!=null){ //每读入一行就写入 同时加上换行 bufferedWriter.write(line); bufferedWriter.newLine(); } //关闭流 if (bufferedReader!=null){ bufferedReader.close(); } if (bufferedWriter!=null){ bufferedWriter.close(); } } }
BufferedInputStream与BufferedOutStream属于字节流,可以用来进行二进制文件(音频、视频、pdf、word…)的读写。
使用BufferedInputStream与BufferedOutStream拷贝文件
package Copy; import java.io.*; public class BufferedCopy_02 { public static void main(String[] args) { String srcPath="d:\\news.txt"; String destPath="d:\\news3.txt"; BufferedOutputStream bos=null; BufferedInputStream bis=null; try { bos= new BufferedOutputStream(new FileOutputStream(destPath)); bis =new BufferedInputStream(new FileInputStream(srcPath)); byte[] bytes=new byte[1024]; int readline=0; while( (readline=bis.read(bytes))!=-1){ bos.write(bytes,0,readline); } System.out.println("拷贝完成!!"); } catch (IOException e) { e.printStackTrace(); }finally { try { /** * 同理也是关闭外层流 */ if (bis!=null){ bis.close(); }if (bos!=null){ bos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
对象流:ObjectInputStream和ObjectOutputStream
对一个对象的数据及类型进行保存
这就牵扯到 序列化与反序列化
序列化 :就是在保存数据时,保存数据的值与数据类型。
反序列化:就是在恢复数据时,恢复数据的值与数据类型。
要让对象支持序列化机制,必须让其类是可序列化的,这个类必须实现以下两个接口之一:
- Serializable(推荐使用):这是一个标记接口,标记该类可以系列化,它里面没有任何方法。
- Externalizable:它继承了Serializable接口,有一些扩充方法,需要实现这些方法。
ObjectInputStream提供了对基本类型及对象类型的反序列化功能
ObjectOutputStream提供了对基本类型及对象类型的序列化功能
package Object_; import java.io.Serializable; public class Dog implements Serializable { private String name; private int age; //serialVersionUID 序列化的版本号,可以提供兼容性 private static final long serialVersionUID=1l; public Dog(String name, int age) { this.name = name; this.age = age; } public Dog() { } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
对 对象的写入(序列化形式)
package Object_; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class ObjectOutputStream_ { public static void main(String[] args) { String ObjPath="d:\\dog.dat"; ObjectOutputStream oos=null; try { oos = new ObjectOutputStream(new FileOutputStream(ObjPath)); oos.writeObject(new Dog("小花",5)); System.out.println("写入完成(序列化形式)..."); } catch (IOException e) { e.printStackTrace(); }finally { if (oos!=null){ try { oos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
对对象的读取
package Object_; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ObjectInputStream_ { public static void main(String[] args) { String ObjPath="d:\\dog.dat"; ObjectInputStream ois=null; try { ois = new ObjectInputStream(new FileInputStream(ObjPath)); Dog o = (Dog)ois.readObject(); System.out.println(o); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } finally { if (ois!=null){ try { ois.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
注意事项
读写顺序要一致。
要求实现序列化或反序列化对象,需要实现Serializable接口。
序列化的类中建议添加SerialVersionUID,提高版本兼容性。
序列化对象时,默认将里面的所有属性都进行序列化,但除了static或transient修饰的成员。
(1)为什么要用transient关键字?
在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。(2)transient的作用
transient是Java语言的关键字,用来表示一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包括在序列化的结果中。而非transient型的变量是被包括进去的。序列化对象时,要求里面属性的类型也需要实现序列化接口。
序列化具有可继承性,某类实现了序列化,则它的所有子类默认实现了序列化。
类型 | 默认设备 | |
---|---|---|
System.in 标准输入 | InputStream | 键盘 |
System.out 标准输出 | PrintStream | 显示器 |
package Standard; import java.io.InputStream; import java.util.Scanner; public class InputAndOutput { public static void main(String[] args) { /** * public final static InputStream in = null; * 1.编译类型是InputStream * 2.运行类型是BufferedInputStream * 表示的是标准输入 ->键盘 */ System.out.println(System.in.getClass()); Scanner scanner = new Scanner(System.in);//例如 /** *public final static PrintStream out = null; * 1.编译类型是PrintStream * 2.输出类型是PrintStream * 表示的是默认输出 ->显示器 * */ System.out.println(System.out.getClass()); System.out.println("你真帅!");//例如 } }
转换流:InputStreamReader与OutputStreamWriter
作用是将字节流转换为字符流(解决字符乱码问题)
介绍:
- InputStreamReader是Reader的子类,可以将InputStreamReader(字节流)包装(转换)成Reader(字符流)
- OutputStreamWriter是Writer的子类,可以将OutputStreamWriter(字节流)包装(转换)成Writer(字符流)
- 当处理纯文本数据时,使用字符流效率更高,并且可以有效解决中文乱码问题,所以建议将字节流转化为字符流
- 可以在使用时制定编码格式(例如:utf-8,gbk,gb2312等)
未更改文件的字符编码时
[
更改后:出现乱码
演示InputStreamReader_解决中文乱码问题
package transformation; import java.io.*; /** * 演示InputStreamReader_解决中文乱码问题 */ public class InputStreamReader_ { public static void main(String[] args) throws IOException { String filePath="d:\\news1.txt"; /** * 1.将FileInputStream转化为InputStreamReader * 2.指定编码格式 */ InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk"); //3.将InputStreamReader传入BufferedReader BufferedReader bufferedReader=new BufferedReader(isr); /** * 将2.3步结合到一起 * BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"gbk")); */ //4.读取 String s=bufferedReader.readLine(); System.out.println(s); //5.关闭外层流 bufferedReader.close(); } }
演示使用OutputStreamWriter 使用指定编码写入文件
package transformation; import java.io.*; /** * 演示使用OutputStreamWriter 使用指定编码写入文件 */ public class OutputStreamWriter_ { public static void main(String[] args) throws IOException { String filePath="d:\\news.txt"; OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), "gbk"); osw.write("转换流写入"); osw.close(); System.out.println("写入成功"); } }
PrintStream(字节流)与PrintWriter(字符流)
打印流只有输出流没有输出流
字节打印流PrintStream
package Writer_; import java.io.IOException; import java.io.PrintStream; /** * 演示PrintWriter(字节打印流) */ public class PrintStream_ { public static void main(String[] args) throws IOException { PrintStream ps=System.out; //在默认情况下 PrintStream的输出位置是 标准输出,即显示器 控制台 ps.print("这是标准输出!!!"); //因为print的底层是write,所以可以直接调用write ps.write("这是标准输出!!!".getBytes()); ps.close(); //修改打印位置 System.setOut(new PrintStream("d:\\news.txt")); System.out.println("你好!PrintStream"); } }
字符打印流PrintWriter
package Writer_; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class PrintWriter_ { public static void main(String[] args) throws IOException { //修改打印位置 PrintWriter pw=new PrintWriter(new FileWriter("d:\\news.txt")); // PrintWriter pw=new PrintWriter(System.out); pw.write("你好 java~~~~"); pw.close(); } }
例如读取连接数据库的配置文件
package properties_; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; /** *这是使用传统方式进行读取 *比较繁琐 *若只需要某一个值,例如ip 还需要进一步判断 */ public class properties01 { public static void main(String[] args) throws IOException { //读取myql.properties并得到 ip user pw BufferedReader br = new BufferedReader(new FileReader("src\\properties_\\mysql.properties")); String line=null; while ((line=br.readLine())!=null){ String[] spLit=line.split("="); System.out.println(spLit[0]+"的值是"+spLit[1]); } br.close(); } }
使用properties类读取配置文件
介绍:
专门读取配置文件的集合类
配置文件的格式:
键=值
键=值
注意:键值对不需要有空格,值不需要用引号。默认类型是String
String | getProperty(String key) | 用指定的键在此属性列表中搜索属性。 |
---|---|---|
String | getProperty(String key ,String defaultValue) | 用指定的键在属性列表中搜索属性。 |
void | list(PrintStream out) | 将属性列表输出到指定的输出流 |
void | list(PrintWriter out) | 将属性列表输出到指定的输出流。 |
void | load(InputStream inStream) | 从输入流中读取属性列表(键和元素对)。 |
void | load(Reader reader) | 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 |
Object | setProperty(String key, String value) | 调用 Hashtable 的方法 put 。 |
void | store(OutputStream out, String comments) | 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。 |
void | store(Writer writer, String comments) | 以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符。 |
package properties_; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.Parameter; import java.util.Properties; public class properties02 { public static void main(String[] args) throws IOException { /** * 使用Properties读取mysql.properties文件 */ //1.创建Properties对象 Properties properties=new Properties(); //2.加载指定配置文件 properties.load(new FileReader("src\\properties_\\mysql.properties")); //3.把k-v现实至打印台 properties.list(System.out); //4.根据k获取v System.out.println("账号是"+properties.getProperty("user")); System.out.println("密码是"+properties.getProperty("pwd")); } }
使用Properties创建修改配置文件
package properties_; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.Properties; public class properties03 { public static void main(String[] args) throws IOException { //Properties创建配置文件,修改配置文件内容 //Properties的父类就是HashTable,底层就是HashTable核心方法 Properties properties=new Properties(); //创建 //如果该文件没有key则为创建 有key则为修改 properties.setProperty("user","汤姆");//注意使用FileOutputStream保存时,保存的是中文的unicode码值 properties.setProperty("pwd","123"); properties.setProperty("charset","utf8"); //将k-v存储到文件中即可 中文注释在存储时也会保存的是unicode码 properties.store(new FileOutputStream("src\\properties_\\mysql.properties"),"这个是注释"); System.out.println("保存配置成功~"); } }
package Copy; import java.io.*; public class copyDirectoryDemo { public static void main(String[] args) { File srcFolder = new File("C:\\Users\\xuanlong\\Desktop\\日语"); File destFolder = new File("C:\\Users\\xuanlong\\Desktop\\日语Copy"); fun(srcFolder, destFolder); } public static void fun(File srcFolder, File destFolder) { File[] fileArray = srcFolder.listFiles(); if (!destFolder.exists()) { destFolder.mkdir(); } for (File file : fileArray) { if (file.isDirectory()) { String folderName = file.getName(); File newDestFolder = new File(destFolder, folderName); fun(file, newDestFolder); } else { String fileName = file.getName(); File destFile = new File(destFolder, fileName); copy(file, destFile); } } } public static void copy(File file, File destFile) { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream(file)); bos = new BufferedOutputStream(new FileOutputStream(destFile)); byte[] bys = new byte[1024]; int len = 0; while ((len = bis.read(bys)) != -1) { bos.write(bys, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } 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(); } } } } }