输入/输出流
读取字节的源头被称为输入流,字节的目的地被称为输出流。
获取流对象
//从文件获取流
InputStream in = Files.newInputStream(path);
OutputStream out = Files.newOutputStream(path);
//如果对象是网页
URL url = new URL("https://www.baidu.com/");
InputStream in = url.openStream();
//从一个字节数组读取数据
byte[] bytes = ...
InputStream in = new ByteArrayInputStream(bytes);
字符编码
输入和输出流按顺序读/写字节,文本是要按字符读/写,常用的字符编码是UTF-8或GBK。
一些方法允许通过Charset对象或一个字符串指定字符编码,建议使用StandardCharsets常量。
文本输入
对于较短的文本文件,可以将文件读取到一个字符串 String content = new String(Files.readAllBytes(path), "GBK");
按行读取文件:List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
按流处理:
try(Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)){
}catch (Exception ex){
}
如果输入源并非来自文件:
URL url = new URL("https://www.bilibili.com/");
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()))){
Stream<String> lines = bufferedReader.lines();
}
文本输出
try(PrintWriter out = new PrintWriter(Files.newBufferedWriter(path, StandardCharsets.UTF_8))){
out.write("开始写入...");
out.flush();
}
catch (Exception ex) {
}
如果你已经有一个变量包含了要写的文本:
String content = "内容1";
Files.write(path, content.getBytes(StandardCharsets.UTF_8));
//或者
List<String> lines = new ArrayList<>();
Files.write(path, lines, StandardCharsets.UTF_8);
向文件追加内容:
Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
//或者
Files.write(path, lines, StandardCharsets.UTF_8, StandardOpenOption.APPEND);
文件锁
当多个同时执行的程序对同一个文件进行修改时,它们需要协调;否则,文件很容易被损坏。使用文件锁机制可以解决这类问题。
例如一个简单例子:
FileChannel channel = FileChannel.open(path);
try(FileLock lock = channel.lock()){
}catch (Exception ex){
}
路径、文件和目录
路径
从根路径开始的路径被称为绝对路径,否则就是相对路径。
例子:
//绝对路径
Path path = Paths.get("C:\\Users\\HP\\Desktop\\新建文本文档.txt");
//或者
Path path = Paths.get("C:\\","Users","HP","Desktop","新建文本文档.txt");
//相对路径,路径为文件在工程中的相对路径
Path path = Paths.get("src","in.txt");
//对路径进行组合,调用p.resolve(q)会根据这些规则返回一个路径对象.如果q是绝对路径,则返回结果就是q,否则,返回结果就是先p然后q。
//假设你的程序需要在主目录的相对路径下找配置文件:
Path path = homeDirectory.resolve("myapp/work");
创建文件和目录
//创建一个空文件
Path path = Paths.get("src","in.txt");
if(!Files.exists(path)){
Files.createFile(path);
}
//创建一个空目录
Path path = Paths.get("src","in");
if(!Files.exists(path)){
Files.createDirectory(path);
}
复制、移动和删除文件
如果移动或复制的目标已经存在,则必须指定StandardCopyOption的字段,否则会失败。
//移动,ATOMIC_MOVE选项指定移动应该是原子操作,这样才能确保移动保存成功完成,或继续保留在当前位置
Path fromPath = Paths.get("src","in.txt");
Path toPatch = Paths.get("src","in","in.txt");
Files.move(fromPath, toPatch, StandardCopyOption.ATOMIC_MOVE);
//复制,COPY_ATTRIBUTES选项能覆盖已经存在的目标文件或目录
Files.copy(fromPath, toPatch, StandardCopyOption.COPY_ATTRIBUTES);
删除一个文件boolean deleted = Files.deleteIfExists(path);
HTTP连接
URL类能提供的控制有限,如果想写数据,或获取web资源的额外信息可以使用
- URLConnection类
- HTTP Client API(属于JAVA 9的特性,在运行自己的程序时,你需要在命令行选项中加上:
--add-modules jdk.incubator.httpclient
)
序列化
对象的序列化是一种将一个对象转化成字节方便传送到别处或储存在硬盘上,并且能再从转化成的字节重构对象的机制。
Serializable接口
为了一个对象能被序列化,即把它转化成一段字节,它必须是一个实现了Serializable接口的类的实例。这是一个没有方法的标记接口。
例子:
//所有实例的变量都是基本类型或枚举类型,或者引用其他可序列化对象
class Employee implements Serializable{
private String name;
private double salary;
public Employee(String name, double salary)
{
this.setName(name);
this.setSalary(salary);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
要序列化对象,你需要一个从接收实际字节的OutputStream构造的ObjectOutputStream对象。
Path path = Paths.get("C:\\","Users","HP","Desktop","新建文本文档.txt");
try(ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(path))){
Employee peter = new Employee("Peter", 90000);
Employee paul = new Employee("paul", 190000);
//写入对象
out.writeObject(peter);
out.writeObject(paul);
}catch (Exception ex){
}
//读回对象
try (ObjectInputStream in = new ObjectInputStream(Files.newInputStream(path))){
//然后按照写入的顺序用readObject方法读取对象
Employee e1 = (Employee)in.readObject();
Employee e2 = (Employee)in.readObject();
}
catch (Exception ex){
}
瞬态实例变量
为了实现某些实例变量不被序列化,简单的方法就是给这个变量打一个transient修饰符标记。
private transient double salary;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。