目录
本节很多知识点会在代码中举例注释讲解
文件相关操作
这里主要就是一些方法的用法,没什么难度
接下来的代码就是围绕这些知识点举例
File类
File类描述了一个文件或文件夹【目录】
描述的这个文件或文件夹可以存在也可以不存在
File file = new File(“路径”);
File类中的一些方法
exists() :判断文件是否存在
isFile() :是否是一个文件
isDirectory() :是否是一个文件夹
createNewFile() :创建新文件
mkdir() :创建文件夹 创建一级路径
mkdirs() :创建文件夹 创建多级路径
getName() :获取文件的名字
getPath() :获取文件的路径
getAbsolutePath() :获取绝对路径
getParentFile() :获取父级文件
listFile() :展示文件夹下的文件
listFile(FileFilter filter) :
listFile(FilenameFilter filter) :
length() :文件大小
isHidden() :是否是隐藏
canRead() : 可读
canWrite() : 可写
应用
循环展示某个文件夹下的所有的子文件
删除某个文件夹下的所有的子文件
代码演示
package File学习;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.Date;
public class Demo1 {
public static void main(String[] args) throws IOException {
test1();
deleteDir("test.txt");
isContain("test");
}
//基础
public static void test1() throws IOException {
//判断文件是否存在
File file1 = new File("D://test.txt.txt");//存在
File file2 = new File("D://1.txt");//不存在并不会报错
File fold1 = new File("D://ceshi");//存在
File fold2 = new File("D://ceshi2");//不存在
System.out.println(file1.exists());//true
System.out.println(file2.exists());//false
System.out.println(fold2.exists());//true
System.out.println(fold1.exists());//false
//file2和fold2都是不存在的,接下来我们开始创建
//文件的创建
// boolean f1 = file2.createNewFile();//该方法需要抛异常,返回boolean类型表示是否创建成功
//文件夹的创建
// boolean f2 = fold2.mkdir();//创建一层目录,如果给的是多层目录,就创建不了
// System.out.println(f2);
//boolean f2 = fold2.mkdirs();//创建多层目录,比如D://a//b//c,可以一次性创建三层目录
// System.out.println(file1.delete());//删除文件,返boolean类型
//查看文件相关信息
System.out.println(file1.getName());//得到文件名String类型
System.out.println(file1.length());//文件的大小long类型
System.out.println(file1.canRead());//文件是否可读boolean类型
System.out.println(file1.canWrite());//文件是否可写boolean类型
System.out.println(file1.isHidden());//文件是否隐藏boolean类型
long time = file1.lastModified();//最后修改的时间,long类型的时间可读性查,需要改一下格式
System.out.println(new Date(time));
System.out.println(file1.getPath());//相对路径
System.out.println(file1.getAbsolutePath());//绝对路径
boolean b1 = file1.isDirectory();
boolean b2 = file1.isFile();
File[] files = file1.listFiles();//获取文件夹下面的文件夹以及文件
File[] files1 = fold1.listRoots();//获取所有盘符比如C:、D:
String s = file1.getParent();//父级路径
File f = file1.getParentFile();//父级文件夹
//文件过滤,以fold2文件夹为例
File[] files2 = fold2.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".java");//只找.java结尾的文件
}
});
File[] files3 = fold2.listFiles((dir, name) -> (name.endsWith(".java")));//和上面一样的意思,jdk8后添加的方法
//这两个过滤器差不多用法
File[] files4 = fold2.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().equals("a.java");//只找这个名字的文件夹
//.contains("b");文件名中包含b的文件
}
});
File[] files5 = fold2.listFiles((pathname)->(pathname.getName().endsWith(".java")));
}
//传进来一个多层文件夹路径,删除该文件夹
public static void deleteDir(String s){
File file = new File(s);
File[] files = file.listFiles();
for (File f1:files){
if (f1.isDirectory()){
// System.out.println(f1.getAbsolutePath());
deleteDir(f1.getAbsolutePath());
f1.delete();
}else {
f1.delete();
}
}
file.delete();
}
//传进来一个多层文件夹路径,判断该文件夹下是否有.txt结尾的文件
public static boolean isContain(String s){
//这里当然可以使用正则比较方面,但为了熟练一下刚学的内容,就用这种方法
File[] files = new File(s).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".txt");
}
});
if (files.length>0){
return true;
}else{
File[] files1 = new File(s).listFiles();
System.out.println(s+"有");
for (File f:files1){
System.out.println("\t"+f.getName());
if (f.isDirectory()){
return isContain(f.getPath());
}
}
}
return false;
}
}
IO流
知识点
Input:输入
Output:输出
一个汉字是一个字符
一个汉字是两个字节
所以IO流的分类可以分:
1、方向分:
输入流 (Input Reader)
输出流 (Output Writer)
2、读写方式分:
字节流、字符流
所以根据以上这两种分类,可以分为以下几种IO流:
字节输入流 InputStream
字节输出流 OutputStream
字符输入流 Reader
字符输出流 Writer
流的体系
以上基本信息介绍完了,接下来以InputStream为例子详细介绍,其他的思想都一样
InputStream
可以看出它是一个抽象类,所以是不可以直接实例化对象的,需要实例化子类
可以看到它的相关方法也不多,如果需要详细看的话,可以网上搜以下java api文档都有的,这里每个子类的用法都会有差别,这里只举点例子
所以了解完之后,就知道他是一个抽象类,里面带了一些方法,那么怎么使用,我们不就和前面学的类和抽象类差不多了吗
我们刚学完File文件,所以我们以FileInputStream为例子讲解
InputStream inputStream = new FileInputStream()
FileInputStream()创建这个对象时,调用该构造方法,要满足构造方法的要求然后我们查看该构造方法所以需要传个文件对象,并且调用时,还需要处理构造方法抛出的异常
知识点罗列
InputStream:【抽象类】如果是读取一个字节,紧接着输出到控制台,此时注意汉字,一个汉字如果是UTF-8 占用3个字节,其他格式占【gbk|gb2312】用2个字节。
InputStream字节流,一个字节一个字节读取的。
FileInputStream:常用的一个子类。
read(int i);//一个字节一个字节读取
read(byte[] bs);//
read(bytes[] bs ,int off,int length);//off:读取之后保存到数组中的哪个位置,length:读取的长度是多少
代码演示
在文件中准备这些东西测试
package IO流;
import java.io.*;
public class InputStreamTest {
public static void main(String[] args) {
test3();
}
//先了解一下
public static void test1(){
// InputStream inputStream = new FileInputStream()
//FileInputStream()创建这个对象时,调用该构造方法,要满足构造方法的要求
//这个构造方法方法抛出了异常,所以我们调用的时候需要处理该异常
//当用完之后注意关闭inputStream.close()
File file = new File("D:\\JAVASE\\src\\IO流\\test.txt");
try {
InputStream inputStream = new FileInputStream(file);
/*注意:
InputStream字节流,-一个字节-一个字节读取的。
InputStream :如果是读取一个字节,紧接着输出到控制台,此时注意汉字,
一个汉字如果是UTF-8占用3个字节,其他格式占用2个字节。所以按一个字节读取汉字当然会乱码
*/
//这里以读取英文为例
//读取一个字符,得到的是int类型的,需要转换成char类型的
int c1 = inputStream.read();//此处抛异常
System.out.println((char)c1);
//读文件所有内容,读到文件末尾会返回-1
int c;
while ((c = inputStream.read()) != -1){
System.out.print((char)c);
}
inputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
/*
输出:
h
ello1
hello2
hello3
*/
}
//打印文件中的内容(含中英文)
public static void test2(){
InputStream inputStream = null;
try {
File file = new File("D:\\JAVASE\\src\\IO流\\test.txt");
inputStream = new FileInputStream(file);
//inputStream.read()方法中有一种可以传进去一个字节,可以查看一下
byte[] bytes = new byte[(int) file.length()];//文件的内容要存在这个数组中,所以做一个文件大小的数组存数据
inputStream.read(bytes);//这样就可以把文字读出来,因为中文两个字节(utf-8是三个字符),全被按顺序记录了下来所以按顺序一起输出就能输出文字
String s = new String(bytes);//byte类型传成String类型
System.out.println(s);
}catch (Exception e){
e.printStackTrace();
}finally {
if (inputStream!=null){
try {
inputStream.close();//需要抛异常
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//接下来用的都比较少
//截取字符
public static void test3(){
InputStream inputStream = null;
try {
File file = new File("D:\\JAVASE\\src\\IO流\\test.txt");
inputStream = new FileInputStream(file);
byte[] bytes = new byte[(int) file.length()];
inputStream.read(bytes,2,4);//前面跳两个数据,然后读文件前四个字符
//要想不从头读,就跳过几个字节inputStream.skip(n);
String s = new String(bytes);
System.out.println(s);
//输出:( hell )有很多空格,如果想去掉空格就输出s.trim()
}catch (Exception e){
e.printStackTrace();
}finally {
if (inputStream!=null){
try {
inputStream.close();//需要抛异常
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
OutputStream
知识点罗列
OutputStream:【抽象类】字节输出流
FileOutputStream常用子类
write(int i);
write(byte[] bs);
write(byte[]bs,int off,int length);//写数组中从哪个位置开始,写多长
应用
字符流:实现文件复制
代码演示
package IO流;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class OutputStreamTest {
public static void main(String[] args) throws IOException {
//test1();
copy();
}
public static void test1() throws IOException {
OutputStream outputStream = new FileOutputStream(new File("test1.txt"),true);
/*
没有该文件的话会新建该文件,
后面的true如果不加,文件每次写入就会删掉之前的数据,即true表示可追加
*/
outputStream.write('b');//可以是字符、数字会自动转换成字符也可以是byte[]类型的
String s = "hello\n你好\n";//可以换行
outputStream.write(s.getBytes());//字符串转成byte[]类型
outputStream.write(s.getBytes(),2,5);//表示从第二个字符开始写入,连续写5个字符
//截取字符时要注意,一个中文utf-8的格式下是3个字节,如果你截取的字节数把一个文字分开了,那么会把文件里面的内容文字全都弄成乱码
//因为本来一个文字需要三个字节,但你只写入了文字中的一个字节,那么这个字节就可能回和其他字节组合,导致中文全部乱码
//所以我们这为例,从(跳过两个)第三个字节开始截取,截取5个字节就是 l l o \n 你(的第一个字节)
//没错这结果会是乱码,所以截取2,7是可以的,2,10也是可以的
}
//这些明白之后就可以实现文件的复制了
//因为流是以字节的形式保存的,所以图片,视频...都是可以复制的
//这里以图片为例
public static void copy() throws IOException {
FileOutputStream fileOutputStream = null;
FileInputStream fileInputStream = null;
try{
File file = new File("1.jpg");
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream("copy.jpg");
byte[] bytes = new byte[(int) file.length()];
fileInputStream.read(bytes);
fileOutputStream.write(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileOutputStream!=null){
fileOutputStream.close();
}
if (fileInputStream!=null){
fileInputStream.close();
}
}
}
}
Reader
知识点罗列
Reader:字符输入流
InputStreamReader(inputStream)
FileReader(file|filename)
reader(int ch)
reader(char[] cs)
代码演示
package IO流;
import java.io.*;
import java.util.Arrays;
public class ReaderTest {
public static void main(String[] args) {
test03();
}
/*
前面说过Input是按字节读,Reader是按字符读,
那么我们就可以把Input用Reader打包一下,就可以按字符读了,这样中文也是可以一个一个读的
*/
public static void test01(){
InputStream inputStream = null;
Reader reader = null;
try {
inputStream = new FileInputStream("D:/test.txt");
reader = new InputStreamReader(inputStream);//把字节流打包
int c;
while((c=reader.read())!=-1){//Reader读到的内容可以直接保存在char类型中,中文也是可以读的
System.out.print((char)c);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//这里关的话,也得按顺序,很容易理解
try {
if(null!=reader){
reader.close();
}
if(null!=inputStream){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//读整篇文件
public static void test02(){
InputStream inputStream = null;
Reader reader = null;
try {
File file = new File("D:/test.txt");
inputStream = new FileInputStream(file);
reader = new InputStreamReader(inputStream);
char[] cs = new char[(int)file.length()];//因为文件的长度是按字节来算的,所以这里用这个长度当然是给大了
//比如一个中文,按字节算可能是3或者是2,但是按字符来算就只占一个字符
reader.read(cs);
String s = new String(cs);
System.out.println(s.trim());//这样读出来含有很多空格,用trim()方法,去掉前后空格
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(null!=reader){
reader.close();
}
if(null!=inputStream){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
如果每次都打包字节流就很麻烦,所以当然可以直接使用字符流
*/
public static void test03(){
InputStreamReader reader = null;
try {
reader = new FileReader("D:/test.txt");
int c ;
while ((c=reader.read())!=-1){
System.out.print((char)c);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(null!=reader){
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Writer
知识点罗列
Writer:字符输出流
OutputStreamWriter(outputStream)
FileWriter()
代码演示
package IO流;
import java.io.*;
public class WriterTest {
public static void main(String[] args) {
test01();
}
//道理都一样这里就不讲太多了,就讲一下常用
public static void test01(){
OutputStream out = null;
Writer writer = null;
try {
out = new FileOutputStream("D:/out2.txt");
writer = new OutputStreamWriter(out);
writer.write("hello,world.你好!");
writer.flush();//文件写完之后,里面内容还是没有的,需要手动刷新一下,才会到文件中,即用这个方法
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(null!=out){
out.close();
}
if(null!=writer){
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲流
分为字节缓冲流和字符缓冲流,和上面的字节流和字符流基本一样,不同点就是,
缓冲流不管是读还是写,都是每次存到8192字节(8kb)到缓冲区,存满8kb才一次性读/写,然后再进行下一次存8kb
这里多了两个方法newLine(),readLine()
其他基本都一样,上面说的区别我们基本体会不到,所以就可以当成一样的使用,但缓冲流多了两个方法,比较方便,所以可以多使用缓冲流
缓冲流
字节缓冲流:
BufferedInputStream
BufferedOutputStream
字符缓冲流:
BufferedReader:readLine()
BufferedWriter:newLine()
代码演示
字节流
package IO流;
import java.io.*;
public class BufferedStreamTest {
public static void main(String[] args) {
test01();
}
//缓冲流进行文件复制
public static void test01(){
//字节缓冲流
InputStream inputStream = null;
BufferedInputStream bufferedInputStream = null;
OutputStream outputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
inputStream = new FileInputStream("D:/test.txt");
bufferedInputStream = new BufferedInputStream(inputStream);
outputStream = new FileOutputStream("D:/test_01.txt");
bufferedOutputStream = new BufferedOutputStream(outputStream);
int i ;
while ((i=bufferedInputStream.read())!=-1){
bufferedOutputStream.write(i);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(null!=bufferedOutputStream){
bufferedOutputStream.close();
}
if(null!=outputStream){
outputStream.close();
}
if(null!=bufferedInputStream){
bufferedInputStream.close();
}
if(null!=inputStream){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符流
package IO流;
import java.io.*;
public class BufferedTest {
public static void main(String[] args) {
test01();
}
/**
* 字符缓缓冲流
*/
public static void test01(){
//
Reader reader =null;
BufferedReader bufReader =null;
Writer writer = null;
BufferedWriter bufWriter = null;
try {
reader = new FileReader("D:/test.txt");
bufReader = new BufferedReader(reader);
writer = new FileWriter("D:/test03.txt");
bufWriter = new BufferedWriter(writer);
String s ;
while ((s=bufReader.readLine())!=null){//读一行
// System.out.println(s);
bufWriter.write(s);
bufWriter.newLine();//换行
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(null!=bufWriter){
bufWriter.close();
}
if(null!=writer){
writer.close();
}
if(null!=bufReader){
bufReader.close();
}
if(null!=reader){
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
转换流
将字节流转换为字符流,可以传递编码格式,注意保证编码格式的统一
InputStream in = new FileInputStream(“D:/test.txt”);
InputStreamReader reader = new InputStreamReader(in,“UTF-8”);基本都一样,简单演示一下,只演示输出流了
代码演示
package IO流;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class StreamReaderTest {
public static void main(String[] args) {
try {
InputStream in = new FileInputStream("D:/test.txt");
InputStreamReader reader = new InputStreamReader(in);
int c ;
while((c=reader.read())!=-1){
System.out.print((char)c);
}
reader.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
标准输入输出流
System.in
System.out
对输入输出的路径进行更改
package IO流;
import java.io.*;
public class Test {
public static void main(String[] args) {
test01();
}
public static void test02(){
try {
FileOutputStream outputStream = new FileOutputStream("D:/out.txt");
//接下来两句就是对输出进行修改
PrintStream printStream = new PrintStream(outputStream);
System.setOut(printStream);//对System.out.println进行修改为输出在指定位置
for(int i=0;i<26;i++){
System.out.println((char)(97+i));
}
printStream.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/*
* */
public static void test01(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//从键盘读取数据到字节流
String s ;
try {
while((s=reader.readLine())!=null){
if(s.equals("e")||s.equals("exit")){
break;
}
System.out.println("---->"+(char)(s.charAt(0)-32));
}
} catch (IOException e) {
e.printStackTrace();
}
}
//用户输入信息,将这个信息输出到文件中,并将大写转为小写,将小写转换为大写
//用户输入的内容直接输出到文件中。System.out.println();
public static void test03(){
System.out.println("清输入信息,按0结束");
InputStream inputStream = System.in;//键盘读取数据到字节流
int s ;
try {
while((s=inputStream.read())!=-1){
if(s==48){//指定退出字符0为退出
break;
}
if(s!=10){//回车也算一个字符,但我们不需要回车,所以不为回车时输出
System.out.println(s);
}
// System.out.println("---->"+(char)(s-32));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象流
文字讲解不太容易理解,可以先看代码,理解之后再来看这段文字
对象序列化:将的对象保存到磁盘中或对象需要在网络中进行传输
如果序列化:实现序列化的接口,通常加入序列化id
ObjectOutputStream对对象进行序列化。
ObjectInputStream对对象进行反序列化。ObjectInputStream和OjbectOutputSteam:用于存储和读取基本数据类型数据或对象的处理流。它的强 大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
对象的序列化:对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取 了这种二进制流,就可以恢复成原来的Java对象。序列化的好处在于可将任何实现了Serializable接口的 对象转换为字节数据,使其在保存和传输时可被还原。序列化是RMI(Remote Method Invoke-远程方法 调用)过程的参数和返回值都必须实现的机制。而RMI是javaEE的基础,因此序列化机制是JavaEE平台的 基础。如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某 个类是可序列化的,该类必须实现如下两个接口之一,否则会抛出NotSerializableException。通常实现 Serializable
瞬态关键字:当一个类的对象需要被序列化时,某些属性不需要被序列化,这时不需要序列化的属性可以使用关键字 transient修饰。只要被transient修饰了,序列化时这个属性就不会琲序列化了。同时静态修饰也不会被 序列化,因为序列化是把对象数据进行持久化存储,而静态的属于类加载时的数据,不会被序列化。
代码演示
先做一个类
package IO流;
import java.io.Serializable;
public class Person implements Serializable {
//要想实现序列化必须要继承这个接口
private static final long serialVersionUID = -5981579002159173783L;
//这个序列化的ID如果不加的话,反序列化时,当原来的类改变时,就会报错
private int pid;
private String pName;
private String pSex;
private transient int page;
/*
瞬态关键字transient static
当对象的某个属性被transient修饰,或者静态属性,那么不会被序列化,比如这个地方的page,即使之前复制,然后序列化、反序列化得到的这个属性为0
*/
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public String getpName() {
return pName;
}
public void setpName(String pName) {
this.pName = pName;
}
public String getpSex() {
return pSex;
}
public void setpSex(String pSex) {
this.pSex = pSex;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public Person() {
}
}
接下来实现序列化与反序列化
package IO流;
import java.io.*;
public class PersonTest {
public static void main(String[] args) {
test02();
}
//进行序列化
public static void test01(){
//对象序列化
Person person = new Person();
person.setPid(1001);
person.setPage(20);
person.setpName("jerry");
person.setpSex("男");
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:/person.txt"));
//把对象保存在这个文件中,保存的信息我们看不懂,但反序列化时可以实现
out.writeObject(person);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//反序列 江文件中的内容转换为对象
public static void test02(){
try {
//接下来四步就是反序列化
ObjectInput in = new ObjectInputStream(new FileInputStream("D:/person.txt"));
Object obj = in.readObject();
System.out.println(obj);
Person p = (Person) obj;
System.out.println(p.getPid()+"\t"+p.getpName()+"\t"+p.getpSex()+"\t"+p.getPage());
} catch (Exception e) {
e.printStackTrace();
}
}
}