文件
文件流:
文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
常用文件操作
创建一个File对象后,此时只是在程序中创建了一个对象,只有File对象执行了createNewFile方法后才会真正地在磁盘中创建文件
-
new File(String pathname) 根据路径构建一个File对象
-
new File(File parent,String child) 根据父目录+子路径构建
-
new File(String parent,String child) 根据父目录+子路径构建
@Test
public void create01() throws IOException {
String pathname="e:\\news.txt";
final File file = new File(pathname);//这里的File只是一个对象,执行了createNewFile方法后才会真正的在磁盘中创建
final boolean newFile = file.createNewFile();//此时文件在硬盘中创建了
System.out.println("结果为"+newFile);
}
@Test
public void create02() throws IOException {
final File parentFile = new File("e:\\");
String fileName="news2.txt";
final File file = new File(parentFile, fileName);
final boolean newFile = file.createNewFile();
System.out.println("结果为"+newFile);
}
@Test
public void create03() throws IOException {
String parentPath="e:\\";
String fileName="news3.txt";
final File file = new File(parentPath, fileName);
final boolean newFile = file.createNewFile();
System.out.println("结果为"+newFile);
}
-
getName() 获取文件名
-
getAbsolutePath() 获取文件绝对路径
-
getParent() 获取父级目录
-
length() 获取文件大小
-
exists() 文件是否存在
-
isFile() 是否是文件
-
isDirectory() 是否是目录
@Test public void info(){ final File file = new File("e:\\news.txt"); if(file.exists()){ System.out.println("文件存在"); System.out.println("文件名="+file.getName());//获取文件名 System.out.println("文件绝对路径="+file.getAbsoluteFile());//获取文件绝对路径 System.out.println("文件父级目录="+file.getParent());//获取文件父级目录 System.out.println("文件字节数(utf-8中,一个英文字母对于一个字节,一个汉字对应三个字节)="+file.length()); System.out.println("文件是否是文件 "+file.isFile()); System.out.println("文件是否是目录 "+file.isDirectory()); }else { System.out.println("文件不存在"); } }
目录的操作和文件删除:
-
mkdir() 创建一级目录
-
mkdirs() 创建多级目录(包括一级目录)
-
delete() 删除空目录或文件
//判断目录是否存在,若存在就删除,不存在就创建 @Test public void m2() throws IOException { String directoryPath="e:\\mkdirPath"; final File file = new File(directoryPath); if (file.exists()){ if(file.delete()){ System.out.println("目录删除成功"); }else{ System.out.println("目录删除失败"); } }else { if (file.mkdirs()){ System.out.println("目录创建成功"); }else { System.out.println("目录创建失败"); } } }
IO流的原理和分类
Java IO流原理
I/O是Input/Output的缩写。I/O技术是非常实用的技术,用于数据传输。如读/写文件,网络通讯等。Java程序中,对于数据的输入输出接口以“流(stream)” 的方式进行。
流的分类
按操作数据单位不同分为:字节流(8 bit),字符流(按字符)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流/包装流
(抽象基类) | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
这四个类都是抽象类,需要使用它们的子类
InputStream 字节输入流
InputStream是所有类字节输入流的超类
常用子类:
- FileInputStream 文件输入流
- BufferedInputStream:缓冲字节输入流
- ObjectInputStream:对象字节输入流
FileInputStream:
@Test
public void readFile01(){
String pathName="e:\\hello.txt";
FileInputStream fileInputStream=null;
int readData=0;
byte[] bytes=new byte[8];
int readLen=0;
try {
fileInputStream = new FileInputStream(pathName);
while ((readLen=fileInputStream.read(bytes))!=-1){//read()读取一个字节,效率较低 read(byte[] b)读取b个字节,效率较高
System.out.println(readLen);
System.out.println(new String(bytes,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream:
public static void main(String[] args) {
String path="e:\\a.txt";
FileOutputStream fileOutputStream=null;
try {
fileOutputStream = new FileOutputStream(path,true);//如果在构造器中加一个true就表示在原有内容追加
//fileOutputStream.write('H');//向文件输出单个字符
String str="hs,testFileOutputStream";
fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));//将字符串转换为字节数组后输出到文件
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件复制:
public static void main(String[] args) {
String srcFilePath="e:\\1.png";
String destFilePath="e:\\2.png";
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
try {
fileInputStream=new FileInputStream(srcFilePath);
fileOutputStream=new FileOutputStream(destFilePath,true);
byte[] buf=new byte[1024];
int readLen=0;
while ((readLen=fileInputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,readLen);
}
System.out.println("文件复制完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileInputStream!=null){
fileInputStream.close();
}
if (fileOutputStream!=null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader
new FileReader(File/String)
read():每次读取一个字符,如果到文件末尾返回-1
read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果读到末尾返回-1
相关API:
- new String(char[]):将char[]转换成String
- new String(char[],off,len):将char[]的指定部分转换成String
使用FileReader读取字符:
public static void main(String[] args) {
String filePath="e:\\program.txt";
FileReader fileReader=null;
try {
fileReader=new FileReader(filePath);
int data;//读取单个字符结果
char[] chars=new char[8];
int readLen;
//(data=fileReader.read())!=-1 读取单个字符
while ((readLen=fileReader.read(chars))!=-1){
System.out.print(new String(chars,0,readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader!=null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter
new FileWriter(File/String)覆盖模式(仅覆盖当次输入,对文件原数据无影响)
new FileWriter(File/String,true) 追加模式
write(int):写入一个字符
write(char[]):写入多个字符
write(char[],off,len):写入指定数组的指定部分
write(string):写入多个字符
write(string,off,len):写入字符串的指定部分
相关API:
toCharArray:将String转换成char[]
注意:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件
public static void main(String[] args) {
String filePath="e:\\fileWriterTest.txt";
FileWriter fileWriter=null;
try {
char[] chars= {'A','b','c'};//a 97 b 98 c 99 A 65
fileWriter = new FileWriter(filePath);
fileWriter.write('a');//单个字符
fileWriter.write("String字符串");//String字符串
fileWriter.write(chars);//字符数组
fileWriter.write("前五个字符的String",0,5);
fileWriter.write("前五个字符的String".toString(),0,5);
fileWriter.write(chars);//字符数组
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileWriter.close();//close相当于flush+关闭
} catch (IOException e) {
e.printStackTrace();
}
}
}
节点流和处理流
-
节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
-
处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更加强大的读写功能,也更加灵活。如BufferedReader、BufferedWriter
BufferedReader类中,有一个属性Reader,既可以封装任何一个节点流。该节点流可以是任意的。只要是Reader的子类就可以
节点流和处理流的区别和联系:
- 节点流是底层流/低级流,直接和数据源相连
- 处理流(包装流) 包装节点流,即可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
- 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源项链
处理流的功能主要体现在以下两个方面:
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便