File类——操作文件的类
1. 一个File类的对象,表示了磁盘上的文件或目录。
2. File类提供了与平台无关的方法来对磁盘上的文件或目录进行创建或删除等常用操作。
3. 不能通过File类的对象存取文件的内容
public class FileTest {
public static void main(String[] args) {
File file1 = new File("e:/test");//给出路径
//(Windows中使用\,而Linux中使用/表示目录分隔符,操作时最好使用File.separtor表示分隔符)
//因此可将路径单独定义出来为String path="d:"+File.separtor+"test.txt"
if(!file1.exists()){//如果不存在则创建
boolean ok = file1.mkdir();//根据指定的路径创建文件夹
System.out.println("file1是否创建成功:"+ok);
}
File file2 = new File("e:\\test\\test\\io");
if(!file2.exists()){
boolean ok = file2.mkdirs();//mkdirs()为创建指定文件夹以及所有需要的父目录
//一层一层全部创建好,而mkdir只创建第一层
System.out.println("file1是否创建成功:"+ok);
}
File file3 = new File("e:/test/test.txt");
if(!file3.exists()){
try {
boolean ok = file3.createNewFile();
//根据规定的路径创建新文件,使用的是绝对路径,完整的路径
System.out.println("file3是否创建成功:" + ok);
} catch (IOException e) {
e.printStackTrace();
}
}
File file4 = new File("Test.java");//使用相对路径,在当前程序的运行路径之下(E:\4.16_NEW\code\JavaPrc\)
if (!file4.exists()) {
try {
file4.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
File file5 = new File(file2,"test.java");//在file2最底层的文件夹内创建,即在io中创建
if(!file5.exists()){
try {
boolean ok = file5.createNewFile();
System.out.println("file5是否创建成功:" + ok);
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("file1是目录吗:" + file1.isDirectory());
System.out.println("file1是文件吗:" + file1.isFile());
System.out.println("file2是目录吗:" + file2.isDirectory());
System.out.println("file2是文件吗:" + file2.isFile());
System.out.println("file3是目录吗:" + file3.isDirectory());
System.out.println("file3是文件吗:" + file3.isFile());
System.out.println("file3的相对路径:" + file3.getPath());
System.out.println("file4的相对路径:" + file4.getPath());
System.out.println("file3是绝对路径吗:" + file3.isAbsolute());
System.out.println("file4是绝对路径吗:" + file4.isAbsolute());
//一些文件属性
System.out.println("文件大小:" + file3.length());
System.out.println("文件可读:" + file3.canRead());
System.out.println("文件可写:" + file3.canWrite());
System.out.println("文件可执行:" + file3.canExecute());
System.out.println("文件是否隐藏:" + file3.isHidden());
System.out.println("文件最后修改时间:" + file3.lastModified());
System.out.println("文件最后修改时间:" + String.format("%tF %
JAVA文件操作工具类
//写一个文件工具类,可以统计某个文件或文件夹的大小,可以删除一个文件或目录,可以拷贝一个目录
public class FileUtils {
public static void main(String[] args) {
}
// 拷贝一个目录
public static void copyDir(File from, File to) throws IOException {
if (from.isFile()) {
copyFile(from, new File(to, from.getName()));
// getname()返回的是此抽象路径名表示的文件或目录的名称,即表示给to文件赋名为getname得到的文件名称
return;
}
File[] fs = from.listFiles();
File toDir = new File(to, from.getName());
if (!toDir.exists()) {// 创建文件夹
toDir.mkdir();
}
for (int i = 0; i < fs.length; i++) {
copyDir(fs[i], toDir);
}
}
// 拷贝一个文件
public static void copyFile(File from, File to) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
long start = System.currentTimeMillis();
in = new FileInputStream(from);
out = new FileOutputStream(to);
byte[] bs = new byte[1024 * 10];// 创建缓冲区
int len = in.read(bs);
while (len != -1) {
out.write(bs, 0, len);
len = in.read(bs);
}
System.out.println("拷贝文件使用时间为:"
+ (System.currentTimeMillis() - start) + "毫秒");
} finally {// 保证流可以被关闭
try {
if (in != null) {
in.close();
}
} finally {
if (out != null) {
out.close();
}
}
}
}
// 删除一个文件或者目录
public static void delete(File f) {
if (f.isFile()) {
f.delete();
return;
}
File[] fs = f.listFiles();
for (int i = 0; i < fs.length; i++) {
delete(fs[i]);// 删除文件夹里的各个文件
}
f.delete();// 删除文件夹
}
// 统计一个文件或目录的大小
public static long getsize(File f) {
if (f.isFile()) {// 若为文件则直接返回大小
return f.length();
}
File[] fs = f.listFiles();// 若为文件夹则计算大小
long total = 0;
for (int i = 0; i < fs.length; i++) {
total += getsize(fs[i]);
}
return total;
}
// 列出一个目录中的文件,并计算总数量
static int count = 0;
public static void showFiles(File f) {
String[] files = f.list();
// 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录
// File[] file = f.listFiles();//列出目录的完整目录
System.out.println(f.getAbsolutePath() + "目录下所有文件:");
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);//循环输出所有的文件
}
count = 0;
showJavaFiles(f);
System.out.println(f + "目录下有" + count + "个java文件");
}
// 获取指定目录下的所有java文件
public static void showJavaFiles(File f) {
if (f.isFile()) {
count++;
System.out.println(f.getAbsolutePath());
return;
}
File[] fs = f.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {// 路径直接返回true
return true;
}
return pathname.getName().endsWith(".java");
}
});
for (int i = 0; i < fs.length; i++) {
showJavaFiles(fs[i]);
}
}
}
流—Stream概述
1. 在程序中所有的数据都是以流的方式来进行传输或保存的,程序需要数据时要使用输入流来读取数据,而程序需要将一些数据保存起来的时候,就要使用输出流。
2. 流的操作主要有字节流和字符流两大类,两类都有输入和输出操作。字节流输出数据主要使用OutputStream类完成,输入使用InputStream类完成。字符流输出数据主要使用Writer类完成,输入使用Reader类完成。
3. 主要操作流程

字节流
字节流主要操作byte型类型数据,以byte数组为准。
1. 字节输出流:OutputStream
2. 字节输入流:InputStream
public class StreamTest {
public static void main(String[] args) throws IOException {
//第一步:使用File类找到一个文件
File f = new File("d:" + File.separator + "test.txt");//文件若不存在,会自动创建
//第二步:通过子类实例化父类对象
OutputStream out = new FileOutputStream(f);
//第三步:进行写操作
out.write('I');
String str = "Say Hello Wrold!!";
byte b[] = str.getBytes();//只能输出byte数组,所以将字符串转变为byte数组
out.write(b);//将内容输出
//第四步:关闭输出流
out.close();
InputStream input = new FileInputStream(f);
byte b1[] = new byte[1024];
input.read(b1);//将f中的内容取出,并放到数组b中
input.close();
System.out.println("InputStream读到的内容:" + new String(b1));//将byte数组转为字符串输出
}
}
//InputStream读到的内容:ISay Hello Wrold!!
字符流
程序中一个字符等于两个字节
1. 字符输出流:Writer
2. 字节输出流:Reader
public class ReaderWriterTest {
public static void main(String[] args) throws IOException {
File f = new File("d:" + File.separator + "writer.txt");
// Writer out = new FileWriter(f,true);//第二个参数表示是否是追加模式
Writer out = new FileWriter(f);
out.write(577);
out.write('I');
String str = "Say Hello Wrold!!";
out.write(str);
out.flush();
Reader reader = new FileReader(f);
char c[] = new char[1024];
int len = reader.read(c);
System.out.println("Reader读到的内容:" + new String(c,0,len));
}
}
//Reader读到的内容:?ISay Hello Wrold!!
字节流与字符流区别
字节流在操作时是本身直接进行操作,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件。若是字节流未关闭,依旧可以输出内容,而字符流则不行,除非使用Writer类中的flush()方法

BufferedReader类:用于从缓冲区中读取内容,所有输出的字节数据都将放在缓冲区中,且只能接受字符输入流的实例,所以若为字节流,则必须使用InputStreamReader转换为字符流。
public class BufferedTest {
public static void main(String[] args) throws IOException {
File f = new File("e:/test.txt") ;
OutputStream out = new FileOutputStream(f);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
bw.write("你好\r\n");//利用缓冲区写入
out.write("abc\r\n".getBytes());//直接用字节流写入,未经过缓冲区,会直接写入文件
bw.write("123我爱祖国ABC\r\n");
out.write("123ccc321\r\n".getBytes());
// abc
// 123ccc321
// 你好
// 123我爱祖国ABC
bw.close();
out.close();
InputStream in = new FileInputStream(f);
// BufferedReader br = new BufferedReader(new InputStreamReader(in));
//直接读取指定的文件内容
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//利用键盘输入,没有长度限制,也可以接收中文,为键盘输入的标准格式
System.out.printf("请输入内容:");
String str = null;
while ((str = br.readLine()) != null) {
System.out.println("输入的内容为:" + str);
}
}
}
//请输入内容:www,我今天很开心!
//输入的内容为:www,我今天很开心!
转换流
1. OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,即将一个字符流的输出对象变为字节流的输出对象
2. InputStreamReader:是Reader的子类,将输入的字节流变为字符流,即将一个字节流的输入对象变为字符流的输入对象

public class StreamWriterTransition {
public static void main(String[] args) throws IOException {
File f = new File("d:" + File.separator + "test.txt");
Writer out = new OutputStreamWriter(new FileOutputStream(f));
//将字符输出流out通过OutputStreamWriter转变为字节流进行输出到文件f中(即理解为将字节输出流变为了字符输出流)
out.write("hello world!");
out.close();
Reader reader = new InputStreamReader(new FileInputStream(f));
//将字符输入流reader通过InputStreamReader转变为字节流从文件f中输入到程序(即理解为将字节输入流变为了字符输入流)
char c[] = new char[1024];
int len = reader.read(c);
reader.close();
System.out.println(new String(c,0,len));
}
}
//hello world!
内存操作流
输入输出位置可以设置在文件上,而内存操作流ByteArrayOutputStream、ByteArrayInputStream则可将输出输入的位置设置在内存上

public class ByteArrayStreamTest {
public static void main(String[] args) {
String str = "ABCDEFG";
ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes());//向内存中输入内容
ByteArrayOutputStream out = new ByteArrayOutputStream();
int temp = 0;
while ((temp = in.read()) != -1) {
char c = (char) temp;//将读取的数字变为字符
out.write(Character.toLowerCase(c));//将字符转为小写
}
String str1 = out.toString();
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(str1);
}
}
//abcdefg
管道流
用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流
public class PipedDemo {
public static void main(String args[]) {
Send s = new Send();// 发送数据
Receive r = new Receive();// 接收数据
try {
s.getPos().connect(r.getPis()); // 连接管道
} catch (IOException e) {
e.printStackTrace();
}
new Thread(s).start(); // 启动线程
new Thread(r).start(); // 启动线程
}
}
class Send implements Runnable {
PipedOutputStream pos = new PipedOutputStream(); // 实例化输出流
public void run() {
String str = "Hello World!!!"; // 要输出的内容
try {
pos.write(str.getBytes());
} catch (IOException e1) {
e1.printStackTrace();
}
try {
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public PipedOutputStream getPos() { // 得到此线程的管道输出流
return this.pos;
}
}
class Receive implements Runnable {
PipedInputStream pis = new PipedInputStream(); // 实例化输入流
public void run() {
byte b[] = new byte[1024]; // 接收内容
int len = 0;
try {
len = this.pis.read(b);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
this.pis.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("接收的内容为:" + new String(b, 0, len));
}
public PipedInputStream getPis() {
return this.pis;
}
}
//接收的内容为:Hello World!!!
打印流
public class PrintTest {
public static void main(String arg[]) throws Exception {
PrintStream print = new PrintStream(new FileOutputStream(new File("d:" + File.separator + "test.txt")));
// 现在是使用FileOuputStream实例化,意味着所有的输出是向文件之中
// PrintWriter print = new PrintWriter(new FileOutputStream("Hello.java"));//用法一样
print.print("hello ");
print.println("world!!!");
print.print("1 + 1 = " + 2);
print.println();
print.println(3.14);
print.printf("%tF %

数据操作流
可以按照一定的格式将数据输出,再通过数据输入流按照一定的格式将数据输入,方便地对数据进行处理
public class DateStreamTest {
public static void main(String[] args) throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("e:\\data.txt"));
dos.writeInt(10);//写入整数
double d = 3.14;
dos.writeDouble(d);//写入小数
dos.write(0b00001010);
dos.writeBoolean(true);
dos.writeChar('\t');
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("e:\\data.txt"));
int i = dis.readInt();//读取整数
double db = dis.readDouble();//读取小数
byte b = dis.readByte();
boolean bool = dis.readBoolean();
char c = dis.readChar();
System.out.println(i + " " + db + " " + b + c + bool);//按一定格式输出
dis.close();
}
}
//10 3.14 10 true
对象序列化
1. 把一个对象变为二进制的数据流的一种方法
2. 一个对象要想能够实现序列化,必须实现Serializable接口
3. 当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量
4. 实现序列化的类的对象是可以经过二进制数据流进行传输的,必须依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)
public class ObjectStreamTest {
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Person p = new Person("张三",18,'男');
File f = new File("e:" + File.separator + "person");
ObjectOutputStream outobj = new ObjectOutputStream(new FileOutputStream(f));
outobj.writeObject(p);
outobj.close();
ObjectInputStream inobj = new ObjectInputStream(new FileInputStream(f));
Object obj = inobj.readObject();
inobj.close();
System.out.println(obj);
}
}
class Person implements Serializable{
private static final long serialVersionUID = -5014400645098887262L;
String name;
private int age;
char sex;
transient Dog dog = new Dog();//transient表示该属性是临时的不需要被序列化的
public Person(String name, int age, char sex) {
super();
this.name = name;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "姓名:" + this.name + " 年纪:" + this.age + " 性别:" + this.sex;
}
}
//姓名:张三 年纪:18 性别:男
保存的文件为二进制数据,且不可直接修改,因为会破坏其保存格式
