I/O 输入/输出
Files是一个工具类,用于处理文件、文件夹(目录)
这个工具类不涉及文件中的内容,只是负责建立,删除,判断是否存在等操作。
Linux不严格区分文件还是文件夹,一切都是文件。
package com.example;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Outer {
public static void main(String[] args) throws IOException {
//Path表示路径,即文件或者文件夹的路径和名字
//一个路径是否存在、不区分到底它是文件还是文件夹,这要取决于后续调用的方法
Path file = Path.of("C:\\Users\\pengs\\Downloads\\abc.txt");
Path dir = Path.of("C:/Users/pengs/Downloads/dir");
if(Files.notExists(file))
Files.createFile(file); //建立文件
if(Files.notExists(dir))
Files.createDirectory(dir); //建立文件夹
System.out.println("是否隐藏? " + Files.isHidden(file)); //判断一个文件或者文件夹是否是隐藏的
System.out.println("是否可执行? " + Files.isExecutable(file)); //exe才是可执行
System.out.println("是否可被修改? " + Files.isWritable(file)); //是否可被修改
Files.deleteIfExists(file); //如果文件或文件夹存在则将其删除
Files.deleteIfExists(dir);
}
}
如果涉及到文件内容的操纵,比如读写文件,则需要使用到流。
输入流,输出流
不管是输入还是输出,都以计算机内存为核心。只要有东西进入内存,就算输入流,否则就算输出流。 比如在键盘上打字,这个时候字符进入内存,算作输入
本台计算机上的一个文件传递到另外一台计算机,对于本机来说这是输出,对于另一台计算机来说就是输入。 读文件内容就是输入流,往文件里写内容就是输出流。
输入流我们使用InputStream
输出流我们使用OutputStream
package com.example;
import java.io.*;
import java.util.Arrays;
public class Outer {
public static void main(String[] args) {
//如果文件abc不存在会为你建立,如果存在会覆盖。
try(OutputStream outputStream = new FileOutputStream("abc");
InputStream inputStream = new FileInputStream("abc")) {
outputStream.write('C');
outputStream.write('%');
outputStream.write(97);
outputStream.write("hello".getBytes());
outputStream.write("abcdefghijk".getBytes(), 2, 5); //从第二个字符开始写,写5个字符
outputStream.write('\n');
outputStream.write('9');
outputStream.write(9);
outputStream.write('中');
outputStream.flush(); //一旦遇到这个方法,流中的内容立刻写出,没有缓存。
//close方法被调用之前自动执行flush方法
System.out.println(inputStream.available()); //查看流中有多少个字节可以读取
System.out.println((char)inputStream.read());
System.out.println((char)inputStream.read());
byte[] bytes = new byte[inputStream.available()];
int i = inputStream.read(bytes); //这个方法是将文件的内容读到了这个字节数组的里面,返回值是一共读了多少个字节
System.out.println(new String(bytes));
System.out.println("i的值是:" + i);
} catch (IOException e) {
e.printStackTrace();
}
}
}
中文相关的问题
public class Outer {
public static void main(String[] args) {
//如果文件abc不存在会为你建立,如果存在会覆盖。
try(OutputStream outputStream = new FileOutputStream("abc");
InputStream inputStream = new FileInputStream("abc")) {
outputStream.write("中中文中文".getBytes());
outputStream.flush();
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
System.out.println(new String(bytes));
} catch (IOException e) {
e.printStackTrace();
}
}
}
拷贝文件
带缓冲的流
package com.example;
import java.io.*;
public class Copy {
public static void main(String[] args) {
try (OutputStream out = new BufferedOutputStream(new FileOutputStream("idm1.exe"));
InputStream in = new BufferedInputStream(new FileInputStream("idm.exe"));) {
//BufferedXXXXXputStream 叫做带缓冲区的流,可以加快普通流的速度。
//桥流:将多个流进行组合,从而得到功能更加强大的流。
int data;
while ((data = in.read()) != -1)
out.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
二进制输入和输出(人无法直接读取)
package com.example;
import java.io.*;
public class Copy {
public static void main(String[] args) {
//DataOutputStream和DataInputStream是二进制的输出和输入流
//按照二进制的形式将内容写出,比如double占8个字节,long也占用8个字节
try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("file.dat")));
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("file.dat")));) {
out.writeByte(1);
out.writeShort(1);
out.writeInt(1);
out.writeLong(1);
out.writeFloat(31.4f);
out.writeDouble(3.14);
out.writeChar('C');
out.writeBoolean(true);
out.writeUTF("hello, world"); //写入一个字符串
out.flush();
System.out.println(in.readByte());
System.out.println(in.readShort());
System.out.println(in.readInt());
System.out.println(in.readLong());
System.out.println(in.readFloat());
System.out.println(in.readDouble());
System.out.println(in.readChar());
System.out.println(in.readBoolean());
System.out.println(in.readUTF()); //读出一个字符串
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象输入输出流和序列化
什么是持久化?把内存中的对象存入外存(硬盘,U盘等)的过程叫做持久化。
在Java中,凡是持久化一个对象,都要求实现Serializable接口,这一个规定。这个接口本身没有什么功能,只是起到一个说明和标记的作用。
所谓的序列化,实际上就是把一个对象变成字节流的形式在网络上或者硬盘上进行传递。
import java.io.Serializable;
public class User implements Serializable {
private int id;
private String username;
private String password;
public User(int id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
import java.io.*;
public class Copy {
public static void main(String[] args) {
try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("file.dat")));) {
User tom = new User(1, "Tom", "1234567890");
User jerry = new User(2, "Jerry", "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz");
out.writeObject(tom);
out.writeObject(jerry);
} catch (IOException e) {
e.printStackTrace();
}
try(ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream("file.dat")))) {
User a = (User) in.readObject();
System.out.println(a);
User b = (User) in.readObject();
System.out.println(b);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
持久化和序列化有什么区别?
持久化的前提是序列化。
但是序列化不一定持久化,比如一个对象在两台计算机之间通过网络进行传递,此时也要序列化。但是却不涉及到持久化。
transient只能写在属性/字段的前面,表示这个属性不参与序列化。
字符流: 专门用于处理文本文件,它操作的基本单位是字符。
之所以发明字符流是因为在操纵字符串方面他相对比较便利。
声音或者图片的大小(长度)可能是单数个字节
package com.example;
import java.io.*;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class Copy {
public static void main(String[] args) {
try (PrintWriter out = new PrintWriter("file");
Scanner in = new Scanner(new FileReader("file"))) {
out.println("fjdsklfjdskljflkdsa");
out.printf("%d%-3d", 100, 100);
out.flush();
String str;
while ((str = in.nextLine()) != null)
System.out.println(str);
} catch (FileNotFoundException | NoSuchElementException e) {
//e.printStackTrace();
}
}
}