Java基础九
·
目录
一、文件操作和IO流
官方提供了一组对于文件操作的类, 这些类都存放在java.io包里面


二、API学习方法
1、什么是API
- API指的是一组编程接口和类的集合
- API通常是分模块的, 每一个编程领域有各自的API体系
- API有官方API(JDK中提供的), 第三方API(其他第三方企业或组织提供的)
- 开源API指的是API是开放源代码的
- Application Programming Interface, 应用程序编程接口
2、如何学习API的使用
- 了解API的体系结构,即类图结构(有哪些接口,父类,子类,以及他们之间的关系)
- 了解每个类的使用
3、如何学习一个API中类的使用
看类的结构 (构造方法, 成员方法)
1. 看访问权限修饰符
- private修饰的不能调用
- protected修饰的只能继承后调用
- public修饰的可以调用
2. 看有没有static修饰符
- 成员方法如果是静态(static修饰)的, 无需造对象, 直接使用类名调用
- 成员方法如果是非静态(没有static修饰)的, 需要造对象, 使用对象调用
3. 看方法名
- 通常API中的方法名的命名都非常规范, 看方法名就能够猜到方法的功能
4. 看参数列表
- 参数的类型 参数的名字 参数的个数都要关注到
5. 看返回值类型
- 要关注返回值是什么
6. 看是否有异常返回
- 如果有异常返回, 看是编译时异常还是运行时异常
- 如果是编译时异常, 你要决定是自己try-catch处理,还剩用throws继续往上抛
7. 看方法的注释 (需要很强大的耐心)
8. 看方法底层源码 (需要骨灰级的耐心)
掌握好以上的学习方法
用好IDEA开发工具的API编程提示器
每天勤加练习

三、File类常用的方法
| 方法名 | 作用 |
|---|---|
| getName() | 获取文件名 |
| getParent() | 获取上级目录路径 |
| getParentFile() | 获取上级对象 |
| getPath() | 当前文件路径 |
| canRead() | 是否可读 |
| canWrite() | 是否可写 |
| exists() | 是否存在 |
| isDirectory() | 是否是目录/文件夹 |
| isFile() | 是否是文件 |
| isHidden() | 是否隐藏 |
| lastModified() | 文件最后一次被修改的时间 |
| length() | 文件长度 |
| createNewFile() | 创建文件 |
| delete() | 直接删除文件 |
| deleteOnExit() | 当程序运行结束,JVM终止时才真正调用deleteOnExit()方法实现删除操作 |
| list() | 返回文件夹中所有的filename的数组 |
| listFiles() | 返回文件夹中包含所有file对象的数组 |
| mkdir( ) | 创建一个文件夹 |
| mkdirs() | 创建一个文件夹和它的所有父文件夹 |
| renameTo(dest)方法 | 将文件从原目录移动到dest目录,并改名 |
| setLastModified(time) | 设置文件最后一次被修改的时间 |
| setReadOnly() | 设置只读 |
| setWritable(参数1) | 设置是否可写 |
| setWritable(参数1,参数2) | 设置是否可写,是否仅适用于所有者 |
| setReadable(参数1) | 设置是否可读 |
| setReadable(参数1,参数2) | 设置是否可读,是否仅适用于所有者 |
| setExecutable(参数1) | 设置是否可执行 |
| setExecutable(参数1,参数2) | 设置是否可执行,是否仅适用于所有者 |
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
//File没有无参构造方法
//造一个File对象,必须告诉构造方法File对象指向磁盘中的哪个文件
//File对象可以是文件夹也可以是文件
//路径分隔符有两种写法:1、双反斜杠"\\" 2、单正斜杠"/"
//正斜杠和反斜杠都可以,反斜杠有两个是因为一个反斜杠被Java用作了转义符
//System.out.println("张\r飞");//退格键
//System.out.println("张\n飞");//换行
//System.out.println("张\t飞");//一个tab键
File file = new File("E:\\U\\new\\demo1.txt");
//file对象中的成员变量基本都被private私有化封装起来
//使用file对象进行编程从哪里入手?成员方法!
//1、找成员方法名字( = 功能) 2、看成员方法的参数 3、看成员方法的返回值 4、看成员方法的注释说明
if(!file.exists()){
//file.deleteOnExit();
//当调用deleteOnExit()方法时,只是相当于对deleteOnExit()作一个声明,
// 当程序运行结束,JVM终止时才真正调用deleteOnExit()方法实现删除操作。
// 即该方法是将删除的命令缓存了一下,到服务停止的时候再进行操作!
try {
System.out.println(file.createNewFile()? "创建成功" : "创建失败");
} catch (IOException e) {
e.printStackTrace();
}
}
//还要关注方法是否使用了static修饰,静态方法是属于类的方法,不是属于对象的方法
System.out.println("文件名:" + file.getName());
System.out.println("上级目录路径:" + file.getParent());
System.out.println("当前文件路径:" + file.getPath());
System.out.println("是否可读:" + file.canRead());
System.out.println("是否可写:" + file.canWrite());
System.out.println("是否存在:" + file.exists());
System.out.println("是否是目录/文件夹:" + new File("E:\\U\\new").isDirectory());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否隐藏:" + file.isHidden());
System.out.println("文件最后一次被修改的时间:" + file.lastModified());
System.out.println("文件长度:" + file.length());
File parentFile = file.getParentFile();
System.out.println("上级对象名:" + parentFile.getName());
//System.out.println(file.delete() ? "删除成功" : "删除失败");
// 当调用delete()方法时,直接删除文件,不管该文件是否存在,一经调用立即执行;
try {
new File("E:\\U\\new\\demo2.txt").createNewFile();
new File("E:\\U\\new\\demo3.txt").createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
File file1 = new File("E:\\U\\new");
String[] listNames = file1.list();//返回文件夹中所有的filename的数组
File[] listFiles = file1.listFiles();//返回文件夹中包含所有file对象的一个数组
for (int i = 0; i < listNames.length; i++) {
System.out.println(listNames[i]);
}
for (int i = 0; i < listFiles.length; i++) {
System.out.println(listFiles[i]);
}
//mkdir( )方法创建一个文件夹,成功则返回true,失败则返回false。
// 失败表明File对象指定的路径已经存在,或者由于整个路径还不存在,该文件夹不能被创建。
File file2 = new File("E:\\U\\new\\c");
file2.mkdir();
//mkdirs()方法创建一个文件夹和它的所有父文件夹。
File file3 = new File("E:\\U\\new\\a\\b");
file3.mkdirs();
//使用renameTo()方法,将文件demo1.txt从E:\U\new\目录移动到E:\U\new\a\b\目录,并改名为reDemo.txt
File file4 = new File("E:\\U\\new\\a\\b\\reDemo.txt");
file.renameTo(file4);
file.setLastModified(20220305);
System.out.println(file.lastModified());
if (file.setReadOnly()) {
System.out.println("File set as Read Only");
}
else {
System.out.println("File cannot be set"
+ " as Read Only");
}
if (file.setWritable(true)) {
System.out.println("Writable permission is set");
}
else {
System.out.println("Writable permission cannot be set");
}
//writable --如果为true,允许写访问权限;如果为false,写访问权限是不允许的。
//ownerOnly --如果为true,则写访问权限仅适用于所有者,否则它适用于所有人。
file.setWritable(true,false);
file.setReadable(true);
file.setReadable(true,false);
file.setExecutable(true);
file.setExecutable(true,false);
}
}
四、递归调用
eg1:
public class Demo01 {
static int i = 1;
public static void main(String[] args) {
//方法的递归调用 - 如果无限调用会造成栈内存溢出的错误 StackOverflowError
//如何避免在递归的时候出现StackOverflowError
//给递归一个出口即可
//可以把方法的递归调用理解为一个循环调用同一个方法
//如果循环没有出口的话,就是死循环
a();
}
public static void a(){
if(i == 10000) return;
i++;
System.out.println(i);
a();
}
}
eg2:
import java.io.File;
public class FileSystemDemo {
public static void main(String[] args) {
//使用方法递归来实现文件系统,在任意目录都可以查看其它目录
File root = new File("c:/");
listDirectory(root);
}
/*
* 设计一个可以递归查看目录的方法
* */
static void listDirectory(File file){
if(file.isFile()){//如果file是一个文件,停止递归,这是出口
return;
}else if(file.isDirectory()){//如果file是一个目录,继续递归
File[] listFiles = file.listFiles();//得到该目录中所有的file对象,返回File数组
if(listFiles != null){//空目录返回的listFiles是空数组,需要做非空判断
for (int i = 0; i < listFiles.length; i++) {//迭代listFiles
//在递归过程中想做什么都可以在这里写代码
//例如:找出所有".java"后缀的文件
//listFiles是数组类型,listFiles[i]是File类型,listfiles[i].getName()返回值是String类型
//getName是File类的方法 endsWith()是String类的方法(用来判断某个字符串是不是以参数中的字符串结尾)
if(listFiles[i].isFile() && listFiles[i].getName().endsWith(".java")){
System.out.println(i + " " + listFiles[i].getName());//listFiles[i]就是数组中的每一个File对象
}
listDirectory(listFiles[i]);//递归这个文件对象
}
}
}
}
}
面试题:你有没有看过官方源码和注释?
五、IO 流
1、流的分类
- 按照数据的流动方向
- 输入流 数据从 磁盘 —>> 内存
- 输出流 数据从 内存 —>> 磁盘
- 按照流的方向
- 本地流 磁盘 — 内存
- 网络流 网络 — 内存

- 按照数据在流里面的传输单位
- 字节流 以字节为单位
- 字符流 以字符为单位
import java.io.*;
public class InputStreamDemo {
public static void main(String[] args) {
//造FileInputStream对象赋给变量is,is类型是InputStream类型,发生向上转型
//InputStream is = new FileInputStream(参数);
//InputStream is = new FileInputStream("文件路径");
File file = new File("E:\\U\\new\\demo.txt");
try {
/*
* 1、如果file == null,说明file指针指向的堆区中的对象为空,抛异常
* 2、如果file对象所指向的磁盘中的文件不存在,抛异常
* 3、如果以上条件都不满足,程序会创建一个输入流对象
* 这个输入流对象就是内存与磁盘之间的一个数据传输管道
*
*
* */
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
InputStream is = new FileInputStream(file);//构造方法正常返回this指向的对象地址
int b = 0;
try {
//read()方法一次读取一个字节,如果返回-1说明没有内容可读了
//一个汉字占3个字节,需要read()三次,一个英文字母占1个字节,只需要read()一次
byte[] arr = new byte[3];
int count = 0;
for (int j = 0; j < 7; j++) {
if (count != 7) {
for (int i = 0; i < arr.length; i++) {
arr[i] = (byte)is.read();
//String类有一个以byte数组为参数的构造方法,可以将一个字节数组编码为字符串
}
System.out.println(new String(arr));
count++;
}
}
for (int i = 0; i < 7; i++) {
System.out.println((char)(is.read()));
}
//System.out.println((char)(is.read()));
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {//异常返回一个 FileNotFoundException 对象
e.printStackTrace();
}
}
}
import java.io.*;
public class ReaderDemo {
public static void main(String[] args) {
try {
File file = new File("E:\\U\\new\\demo.txt");
Reader reader = new FileReader(file);
try {
for (int i = 0; i < 14; i++) {
//read()方法一次读一个字符
System.out.println((char) reader.read());
}
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
public class StringDemo {
public static void main(String[] args) {
//String类提供了构造方法,可以对字节数组进行编码为字符串
//ISO-8859-1没有汉字
//GBK一个汉字2个字节,UTF-8一个汉字3个字节
//GBK国内,省存储空间,UTF-8费存储空间,但是万国码,更全
String s = "通达学院";
byte[] sBytes = s.getBytes(); //解码:获取字符串的byte数组
for (byte b : sBytes) {
System.out.println(b);
}
//产生乱码的原因:编码与解码所用字符集不同
byte[] bytes = {-23,-128,-102,-24,-66,-66,-27,-83,-90,-23,-103,-94};
String s1 = new String(bytes); //编码
System.out.println(s1);
System.out.println((int)'男');
System.out.println((char) 30007);
}
}
import java.io.*;
public class OutputStreamDemo {
public static void main(String[] args) {
//输入流要求目标文件必须存在
//输出流不要求目标文件必须存在,只要求目标文件所在的目录必须存在即可
//如果文件不存,在造输出流对象的时候会自动创建该文件
try {
//字节输出流
//false覆盖写 true追加写
OutputStream os = new FileOutputStream("E:\\U\\new\\demo.txt",true);
String s = "三江学院";
//以字节为单位输出,需要把字符串解码为字节
byte[] sBytes = s.getBytes();
try {
os.write(sBytes);
os.write(65);
os.write(66);
} catch (IOException e) {//磁盘分区损坏/磁道、磁针损坏,抛读写异常
e.printStackTrace();
}
} catch (FileNotFoundException e) {//目标文件夹找不到抛异常
e.printStackTrace();
}
}
}
import java.io.*;
public class WriteDemo {
public static void main(String[] args) {
try {
Writer writer = new FileWriter("E:\\U\\new\\demo4.txt");
writer.write("江苏省扬州市");
//getByte()是解码为字符数组
//toCharArray()转为字符数组
String s = "通达学院";
char[] chars = s.toCharArray();
writer.write(chars);
writer.flush();//字符输出流写完后需要调用flush()方法,否则数据无法进入文件
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
public class BinaryDemo {
public static void main(String[] args) {
//输入和输出的路径变量
String inPath = "E:\\ocam\\111.mp4";//输入的视频文件的路径
String outPath = "E:\\U\\new\\111.mp4";//输出的路径
//流的变量(局部变量没有零值,未被赋值之前无法使用)
InputStream in = null;
OutputStream out = null;
DataInputStream dataIn = null;
DataOutputStream dataOut = null;
try {
//造字节流对象
in = new FileInputStream(inPath);
out = new FileOutputStream(outPath);
//造数据流对象
//数据流依赖字节流
dataIn = new DataInputStream(in);
dataOut = new DataOutputStream(out);
//使用dataIn对象调用read()方法读数据,read()方法有一个byte[]参数
//read()很明确需要byte[]数组作为参考,因此在调之前,先把byte[]造出来
byte[] buf = new byte[1024 * 1024];//1MB比1KB更快,1GB没必要浪费内存
//这个read()方法应该在循环中调用,无法一次性读完文件所有数据,也不知道具体要读多少次
//read()方法的返回值:1、能读到字节返回读到的字节长度 2、读不到字节返回-1
int len = -1;
while ((len = dataIn.read(buf)) != -1){
//1、使用dataIn.read(buf)读一次文件,并把读取到的数据放入buf
//2、返回值赋给len
//3、判断len != -1
//4、把buf缓冲区中的数据插入到输出流,写到磁盘当中
dataOut.write(buf,0,len);//从0到len的内容
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//finally块的作用就是关闭try中打开的资源
//流用完后要关闭,不关闭会占用系统资源,关闭的顺序是先开后关
//关闭流 (先开后关)
//in 被 dataIn 依赖;in先开,dataIn后开;dataIn先关,in后关
//out 被dataOut 依赖;out先开,dataOut后开;dataOut先关,out后关
try {
dataIn.close();
in.close();
dataOut.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
六、设计实现文件复制功能

import java.io.*;
/*
* IO工具类
* */
public class IOUtil {
//构造方法私有化,不让外部造对象,
// 该类提供静态方法不需要造对象调用,直接使用类名调用
private IOUtil(){ }
/**
* 复制/下载 文件
* @param srcFile 源文件对象
* @param targetFile 目标文件对象
* @return 成功/失败
*/
public static boolean copy(File srcFile,File targetFile){
String ThreadName = Thread.currentThread().getName();
String srcFileName = srcFile.getName();//源文件名
long srcFileSize = srcFile.length();//源文件大小
System.out.println(ThreadName + "正在下载" + srcFileName + ",文件大小:" + srcFileSize);
InputStream in = null;
OutputStream out = null;
DataInputStream dataIn = null;
DataOutputStream dataOut = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(targetFile);
dataIn = new DataInputStream(in);
dataOut = new DataOutputStream(out);
byte[] buf = new byte[1024 * 1024];
int len = -1;
while ((len = dataIn.read(buf)) != -1){
dataOut.write(buf,0,len);
}
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} finally {
try {
dataIn.close();
in.close();
dataOut.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.File;
public class DownloadThread extends Thread{
File srcFile;
File targetFile;
public DownloadThread(File srcFile,File targetFile){
this.srcFile = srcFile;
this.targetFile = targetFile;
}
@Override
public void run() {
System.out.println(IOUtil.copy(srcFile, targetFile) ?
Thread.currentThread().getName() + "下载成功":
Thread.currentThread().getName() + "下载失败!");
}
}
import java.io.File;
public class DownloadRunnable implements Runnable{
File srcFile;
File targetFile;
public DownloadRunnable(File srcFile, File targetFile){
this.srcFile = srcFile;
this.targetFile = targetFile;
}
@Override
public void run() {
System.out.println(IOUtil.copy(srcFile, targetFile) ?
Thread.currentThread().getName() + "下载成功":
Thread.currentThread().getName() + "下载失败!");
}
}
import java.io.File;
public class DownloadDemo {
public static void main(String[] args) {
//测试copy()方法
String srcDirectoryName = "E:\\ocam\\shipin";
String targetDirectoryName = "D:\\ocam";
//源文件夹对象
File srcDirectoryFile = new File(srcDirectoryName);
//源文件夹中所有的子文件File[]数组
File[] listFiles = srcDirectoryFile.listFiles();
for (File srcFile : listFiles) {
File targetFile = new File(targetDirectoryName,srcFile.getName());
//串行
//方法一:
//IOUtil.copy(srcFile,targetFile);
//并行
//方法二:
//不在主线程中调用copy
//造子线程对象,并把srcFile、targetFile 传给子线程
//DownloadThread dt = new DownloadThread(srcFile,targetFile);
//dt.setName(srcFile.getName() + "子线程");
//dt.start();//启动子线程
//方法三
//可以实现多个线程共享一个runnable对象来实现多线程共享数据比较方便
//DownloadRunnable runnable = new DownloadRunnable(srcFile,targetFile);
//Thread t = new Thread(runnable,srcFile.getName()+"子线程");
//t.start();
//方法四
//接口和抽象类不能直接造对象,因为他们有抽象方法没有实现
//用子类去继承抽象类或实现接口,然后使用子类造对象
//使用匿名内部类
//new Runnable()执行引擎会在此处造一个没有名字的临时类,为匿名类
//该类又是属于当前类的一个内部临时类,又称为角内部类
//故称为匿名内部类,此处存在隐式的extends/implements
//优点:无需写子类,方便
//缺点:无法复用
Thread t = new Thread(new Runnable() {
@Override
public void run() {
//编写隐式匿名内部类中的重写的run()方法中的逻辑代码
//内部类可以访问到外部类的srcFile,targetFile
System.out.println(IOUtil.copy(srcFile, targetFile) ?
Thread.currentThread().getName() + "下载成功":
Thread.currentThread().getName() + "下载失败!");
}
});
t.setName(srcFile.getName() + "子线程");
t.start();//启动子线程
}
}
}
更多推荐



所有评论(0)