JavaIO流学习笔记

文件操作

文件属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 创建文件对象
File(String filename);
File(String directoryPath, String filename);
File(File dir,String filename);

//获取文件属性
public String getName(); //获取文件名字
public boolean canRead(); //判断文件是否可读
public boolean canWrite(); //判断文件是否可写
public boolean exists(); //文件是否存在
public long length(); //获取文件长度(单位是字节)
public String getAbsolutePath(); //获取文件的绝对路径
public String getParent(); //获取文件的父目录
public boolean isFile(); //判断是否是文件而不是目录
public boolean isDirectory(); //判断是否是目录而不是文件
public boolean isHidden(); //判断文件是否是隐藏文件
public long lastModified(); //获取文件最后修改时间

目录操作

1
2
3
4
5
6
7
//File对象是一个目录,则有以下方法
public boolean mkdir();//创建一个目录,存在或创建失败返回false,创建成功返回true
public String[] list(); //用字符串的形式返回目录下全部文件
public File[] listFile(); //用File对象返回目录下全部文件
public String[] list(FilenameFilter obj);//返回字符串形式目录下的指定类型的所有文件
public Flie[] listFile(FilenameFilter obj);//返回File类型形式目录下的指定类型的所有文件
public boolean accept (File dir,String name);//是FilenameFilter接口的方法,可通过重写来筛选出上面两个方法的一些特殊文件。

文件的创建和删除

1
2
3
File file = new File(String dir,String Filename);
public boolean creatnewFile();//创建成功返回true
public boolean delet();//删除成功返回true

运行可执行文件

1
2
Runtime ec = Runtime.getRuntime();
ec.exec(String command);//可以打开机器上的可执行文件或执行一个操作

文件输入、输出

文件字节输入流

1
2
3
4
5
6
FileInputStream(String name);
FileInputStream(File file);
int read();
int read(byte b[]);//把读取的字符存到数组b中
int read(byte b[],int off,int len)//off表示开始读取的位置,len表示读取len个字节
close()//关闭流

文件字节输出流

1
2
3
4
5
6
FileInputStream(String name);
FileInputStream(File file);
int read();
int read(byte b[]);//把读取的字符存到数组b中
int read(byte b[],int off,int len)//off表示开始读取的位置,len表示读取len个字节
close()//关闭流

文件字节输入流

1
2
3
4
5
6
7
FileOutputStream(String name,boolean append);
FileOutputStream(File file,boolean append);
//append 表示是否再文件原有内容的基础上添加,true添加,false删除源文件内容
void write(int n);
void write(byte b[]);
void write(byte b[],int off,int len);
void close();

文件字符输入、输出流

1
2
3
FileReader(同上)
FileWriter(同上)
flush()//用于冲刷缓存区,把内容输出

字符与字节流的区别在于他们的传输单位,一个中文是两个字节所以会有较大区别

缓冲流

1
2
3
4
5
BufferedReader(Read in)
BufferedWriter(Writer out)
readLine()//没有内容会返回null
newLine()//可以输入空行
write(String str)//可以输出内容

随机流

该类的实例支持读取和写入随机访问文件。 随机访问文件的行为类似于存储在文件系统中的大量字节。 有一种游标,或索引到隐含的数组,称为文件指针 ; 输入操作读取从文件指针开始的字节,并使文件指针超过读取的字节。 如果在读/写模式下创建随机访问文件,则输出操作也可用; 输出操作从文件指针开始写入字节,并将文件指针提前到写入的字节。 写入隐式数组的当前端的输出操作会导致扩展数组。 文件指针可以通过读取getFilePointer方法和由设置seek方法

  通俗来讲:我们以前讲的 IO 字节流,包装流等都是按照文件内容的顺序来读取和写入的。而这个随机访问文件流我们可以再文件的任意地方写入数据,也可以读取任意地方的字节。

1
2
3
4
//对文件只读
RandomAccessFile r = new RandomAccessFile(filePath,"r");
//对文件即可读又可写,但是一旦确定了读或者写,那么就不能在变
RandomAccessFile rw = new RandomAccessFile(filePath,"rw");

数组流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
ByteArrayInputStream(byte[] buf);
ByteArrayInputStream(byte[] buf,int offset,int length);
ByteArrayOutputStream();
ByteArrayOutputStream(int size);

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayReader;
import java.io.CharArrayWriter;

public class Example10_10 {
public static void main(String[] args) {
try {
ByteArrayOutputStream outByte = new ByteArrayOutputStream();
byte[] byteContent = "mid-autumn festival ".getBytes();
outByte.write(byteContent);
System.out.println(outByte);
ByteArrayInputStream inByte = new ByteArrayInputStream(outByte.toByteArray());
byte[] backByte = new byte[outByte.toByteArray().length];
inByte.read(backByte);
System.out.println(new String(backByte));
CharArrayWriter outChar = new CharArrayWriter();
char[] charContent = "中秋快乐".toCharArray();
outChar.write(charContent);
CharArrayReader inChar = new CharArrayReader(outChar.toCharArray());
char backChar [] = new char[outChar.toCharArray().length];
inChar.read(backChar);
System.out.println(backChar);
} catch (Exception e) {
e.printStackTrace();
}
}
}

这部分需要注意的点是string,byte,char数据类型之间的相互转化,以及转化中的编码格式,参考资料:https://blog.csdn.net/JackComeOn/article/details/85381788#bytechar_1

对象流

对象的输入输出流的作用: 用于写入对象 的信息和读取对象的信息。 使得对象持久化。

ObjectInputStream : 对象输入流

ObjectOutPutStream :对象输出流

参考样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

//创建要写入磁盘的类,这个类需要实现接口 Serializable(可系列化的)
class Student implements Serializable{

// 在这里保证了serialVersionUID 的唯一性,防止属性变量的临时改变,从而造成写入id与读取id不同
private static final long serialVersionUID = 1L;
int id ; //额外需要添加一个属性

String name ;
transient String sex; //transient修饰属性,表示暂时的,则这个属性不会被写入磁盘
transient int age;

public Student(String name,String sex,int age){
this.name = name;
this.sex = sex;
this.age = age;
}
}


public class objectIO {

/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub

createObj();
readObj();
}

//(一)先写入对象
public static void createObj() throws IOException {
//1.创建目标路径
File file = new File("C:\\Users\\bg\\Desktop\\objTest.txt");
//2.创建流通道
FileOutputStream fos = new FileOutputStream(file);
//3.创建对象输出流
ObjectOutputStream objOP = new ObjectOutputStream(fos);
//4.创建类对象,并初始化
Student stu = new Student("玛丽苏", "男", 18);
//5.向目标路径文件写入对象
objOP.writeObject(stu);
//6.关闭资源
objOP.close();
}

//再读取对象
public static void readObj() throws IOException, ClassNotFoundException {
File file = new File("C:\\Users\\bg\\Desktop\\objTest.txt");
FileInputStream fis = new FileInputStream(file);
ObjectInputStream objIP = new ObjectInputStream(fis);
//读取对象数据,需要将对象流强制转换为 要写入对象的类型
Student stu = (Student)objIP.readObject();
System.out.println("\n name:"+stu.name+"\n sex:"+stu.sex+"\n age:"+stu.age);
objIP.close();
}
}

输出:

1
2
3
name:玛丽苏
sex:null //后面的这连个属性使用了 transient修饰
age:0

序列化与对象克隆(其实就是对象流)

序列化与反序列化就是用来操作对象的,可以把对象存入文件中。
其实就是上面的对象流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class Example10_14 {
public static void main(String[] args) {
MyWin win = new MyWin();
}
}

class MyWin extends JFrame implements ActionListener{
JLabel label = null;
JButton read=null,write=null;
int num=0;
ByteArrayOutputStream out = null;
MyWin()
{
setLayout(new FlowLayout());
label=new JLabel("HOW ARE YOU");
read=new JButton("读如对象");
write=new JButton("写入对象");
read.addActionListener(this);
write.addActionListener(this);
setVisible(true);
add(label);
add(read);
add(write);
setSize(500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
validate();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==write){
try{
out=new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream=new ObjectOutputStream(out);
objectOutputStream.writeObject(label);
num++;
objectOutputStream.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
else if (e.getSource()==read)
{
try{
ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(out.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
JLabel temp = (JLabel)objectInputStream.readObject();
temp.setText(String.valueOf(num));
this.add(temp);
this.validate();
objectInputStream.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}

使用 Scanner 解析文件

把内容先存入内存后再用常用类来解析所需要的内容,优点在于处理速度快,但如果读入的内容较大将消耗较多的内存,即以空间换取时间。
而使用Scanner类和正则表达式来解析内容的特点在于用时间换空间,即:解析速度慢,占用空间少
a.txt的内容:

1
2
3
4
123 4 5 6
123
13
456

样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Scanner解析文件 {
public static void main(String[] args) throws FileNotFoundException {
Scanner in = new Scanner(new File("a.txt"));
while(in.hasNext())
{
System.out.println(in.next());
}
}
}

输出:

1
2
3
4
5
6
7
123
4
5
6
123
13
456

只用Scanner类可以以空格为间隔解析文件,hasnext()判断是(true)否(false)还有内容

配合正则表达式

1
2
3
File file = new File("a.txt");
Scanner sc = new Scanner(file);
sc.useDelimiter(正则表达式);

样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Example10_16 {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("a.txt");
Scanner sc = new Scanner(file);
sc.useDelimiter("[^0123456789.]+");
try {
double score=0;
int n=0;
while (sc.hasNextDouble())
{
score+=sc.nextDouble();
n++;
}
System.out.print("平均分");
System.out.println(score/n);
} catch (Exception e) {
e.printStackTrace();
}
}
}

a.txt:

1
张三37分,李四56分,小明72分,哈哈

输出

1
平均分55.0

文件对话框

1
2
3
4
showSaveDialog(Component a);
showOpenDialog(Component a);
JFileChooser.APPROVE_OPTION;
JFileChooser.CANCEL_OPTION;
坚持原创技术分享,您的支持也将成为我的动力!
-------------本文结束感谢您的阅读-------------
undefined