java 数据流 中文_【Java I/O流】File、字符集、字节流、字符流、缓冲流、数据流、对象流、序列化、try-wi...
I/O流
FileFile 常用方法File 练习:搜索、删除、剪切
字符集(Character Set)字符编码(Character Encoding)字符编码比较乱码
try-with-resources 语句字节流(Byte Streams)FileOutStreamFileInputStream练习 – 将内存中的数据写入文件练习 – 从文件读取数据到内存练习 – 复制
字符流(Character Streams)FileWriterFileReader练习 – 将文本文件的内容逐个字符打印出来
缓冲流(Buffered Streams)缓冲流 – 使用、`close`、`flush`练习 - 价值百万的AI代码练习 – 用缓冲流逐个打印字符练习 – 转换文本文件编码
Scanner格式化输出`PrintStream``PrintWriter`
数据流(Data Streams)对象流(Object Streams)、序列化(Serialization)对象的序列化和反序列化serialVersionUIDtransient练习 - 序列化与反序列化`ObjectOutputStream` – 序列化`ObjectInputStream` – 反序列化
Files工具类
Java笔记目录可以点这里:Java 强化笔记(适合有基础的童鞋,不适合小白)
I/O流 全称是 Input/Output Stream,译为“输入/输出流”。
不管什么数据,本质上都是二进制而已,所谓 I/O流,就是将这些 01 二进制进行传输。
I/O流的常用类型都在 java.io 包中:
类型输入流输出流字节流(Byte Streams)InputStreamOutputStream字符流(Character Streams)ReaderWriter缓冲流(Buffered Streams)BufferedInputStream、BufferedReaderBufferedOutputStream、BufferedWriter数据流(Data Streams)DataInputStreamDataOutputStream对象流(Object Streams)ObjectInputStreamObjectOutputStream
File
一个 File 对象就代表一个文件或目录(文件夹)
// file1、file2都能访问test.txt文件
File file1 = new File("F:\\Files\\Texts\\test.text");
File file2 = new File("F:/Files/Texts/test.text");
名字分隔符(name separator):File.separator
在 UNIX、Linux、Mac 系统中:正斜杠 /在 Windows 系统中:反斜杠 \
路径分隔符(path separator):File.pathSeparator
在 UNIX、Linux、Mac 系统中:冒号:在 Windows 系统中:分号;
是否区分大小写
在 Windows、Mac 系统中:文件名、目录名不区分大小写在 UNIX、Linux 系统中:文件名、目录名区分大小写
File 常用方法
获取文件或目录的名称:String getName()获取父路径:String getParent()获取父文件:File getParentFile()获取路径:String getPath()获取绝对路径:String getAbsolutePath()获取绝对路径形式的文件:File getAbsoluteFile()最后一次修改的时间:long lastModified()文件的大小(不支持目录):long length()
是否绝对路径:boolean isAbsolute()文件或目录是否存在:boolean exists()是否目录(文件夹):boolean isDirectory()是否文件:boolean isFile()是否隐藏:boolean isHidden()是否可读:boolean canRead()是否可写:boolean canwrite()
获取当前目录下所有文件、目录的名称 String[] list() String[] list(FilenameFilter filter)获取当前目录下所有文件、目录 File[] listFiles() File[] listFiles(FilenameFilter filter) File[] listFiles(FileFilter filter)
创建文件(不会覆盖旧文件):boolean createNewFile()删除文件或空目录(不经过回收站,慎重!):boolean delete()创建当前目录:boolean mkdir()创建当前目录(包括不存在的父目录):boolean mkdirs()剪切到新路径(可以改名,很有用):boolean renameTo(File dest)
设置修改日期:boolean setLastModified(long time)设置只读权限:boolean setReadOnly()设置写权限: boolean setWritable(boolean writable, boolean ownerOnly) boolean setWritable(boolean writable)设置写权限: boolean setReadable(boolean readable, boolean ownerOnly) boolean setReadable(boolean readable)
File 练习:搜索、删除、剪切
package com.mj;
import java.io.File;
import java.util.function.Consumer;
public class Files {
/**
* 搜索目录下的所有文件
* @param dir 目录
* @param operation 执行的操作
*/
public static void search(File dir, Consumer operation){
if(dir == null || operation == null) return;
// 目录不存在 或者 传入的是文件, 不执行操作
if(!dir.exists() || dir.isFile()) return;
File[] subfiles = dir.listFiles();
for (File sf : subfiles) {
operation.accept(sf);
if(sf.isFile()) continue; // 如果是文件,跳过,进行后面的搜索
search(sf, operation); // 如果是文件夹, 递归搜索该文件夹
}
}
/**
* 删除文件夹
* @param file
*/
public static void delete(File file){
// 传入null 或者 文件夹不存在, 不执行操作
if(file == null || !file.exists()) return;
clean(file);
file.delete();
}
/**
* 清空文件夹中文件
* @param dir
*/
public static void clean(File dir){
// 如果文件夹不存在 或者 传入的是文件, 不执行操作
if(dir == null || !dir.exists() || dir.isFile()) return;
File[] subfiles = dir.listFiles();
for (File sf : subfiles) {
delete(sf);
}
}
/**
* 剪切文件或文件夹到目标路径
*/
public static void move(File src, File dest){
if(src == null || dest == null) return;
// 如果源File不存在 或者 目标File 已经存在, 不执行操作
if(!src.exists() || dest.exists()) return;
mkparents(dest);
src.renameTo(dest);
}
/**
* 创建父路径
*/
private static void mkparents(File file){
File parent = file.getParentFile();
if(parent == null) return;
parent.mkdirs();
}
}
import java.io.File;
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) throws Exception {
// file1、file2都能访问test.txt文件
// File file1 = new File("F:\\");
File file = new File("F:/");
Files.search(file, (sub) -> {
if (sub.isFile()) { // 是文件
System.out.println("\t文件:" + sub.getName());
} else {
System.out.println("目录:" + sub.getName());
}
});
}
}
这个测试类可以像下面这样读取整个F盘的文件及文件夹:
字符集(Character Set)
在计算机里面
一个中文汉字是一个字符一个英文字母是一个字符一个阿拉伯数字是一个字符一个标点符号是一个字符…
字符集(简称 Charset):由字符组成的集合字符集(Character Set)
常见的字符集有:
ASCII:128个字符(包括了英文字母大小写、阿拉伯数字等)ISO-8859-1:支持欧洲的部分语言文字,在有些环境也叫 Latin-1GB2312:支持中文(包括了 6763 个汉字)BIG5:支持繁体中文(包括了 13053 个汉字)GBK:是对 GB2312、BIG5 的扩充(包括了 21003 个汉字),支持中日韩GB18030:是对 GBK 的扩充(包括了 27484 个汉字)
ISO-8859-1、GB2312、BIG5、GBK、GB18030、Unicode 中都已经包括了 ASCII 中的所有字符
字符编码(Character Encoding)
每个字符集都有对应的字符编码,它决定了每个字符如何转成二进制存储在计算机中。
一个字节 = 8位二进制,即 1Byte = 8bit关于一个字符等于多少字节,是不确定的,主要看编码方式。
ASCII:单字节编码,编码范围是 0x00 ~ 0x7F (0 ~ 127)
ISO-8859-1:单字节编码,编码范围是 0x00 ~ 0xFF
0x00 ~ 0x7F 和 ASCII 一致,0x80 ~ 0x9F 是控制字符,0xA0 ~ 0xFF 是文字符号
GB2312、BIG5、GBK:采用双字节表示一个汉字
GB18030:采用单字节、双字节、四字节表示一个字符
Unicode:有 Unicode、UTF-8、UTF-16、UTF-32 等编码,最常用的是 UTF-8 编码
UTF-8 采用单字节、双字节、三字节、四字节表示一个字符
字符编码比较
如果 String.getBytes 方法没有传参,就使用 JVM 的默认字符编码,一般跟随 main 方法所在文件的字符编码。
可以通过 Charset.defaultCharset 方法获取 JVM 的默认字符编码
Charset 类的全名是 java.nio.charset.Charset
乱码
计算机中真正的代码其实是二进制,所以转到它是编码,它转别的就是解码。
【字符串】转为【二进制】的过程:编码(Encode)【二进制】转为【字符串】的过程:解码(Decode)
编码、解码时使用的字符编码必须要保持一致,否则会造成乱码。
String str1 = "Java不难";
// UTF-8编码为二进制: [74, 97, 118, 97, -28, -72, -115, -23, -102, -66]
byte[] bytes = str1.getBytes("UTF-8");
// GB18030解码: Java涓嶉毦
String str2 = new String(bytes, "GB18030");
// UTF-8解码: Java不难
String str3 = new String(bytes, "UTF-8");
try-with-resources 语句
从Java7开始推出的try-with-resources语句(可以没有catch、finally)
try(资源1; 资源2; ...) {
} catch (Exception e) {
} finally {
}
可以在try后面的小括号中声明一个或多个资源(resource)
实现了 java.lang.AutoCloseable 接口的实例,都可以称之为是资源
不管try中的语句是正常还是意外结束
最终都会自动按顺序调用每一个资源的 close 方法(close 方法的调用顺序与资源的声明顺序相反)调用完所有资源的 close 方法后,再执行 finally 中的语句
字节流(Byte Streams)
字节流的特点:
一次只读写一个字节最终都继承自 InputSteam、OutputStream
常用的是字节流有 FileInputStream、FileOutputStream
字节流结构预览:
FileOutStream
// 字节流
// true表示追加内容,并非覆盖原来内容
FileOutputStream fos = new FileOutputStream("F:/1.txt", true);
fos.write("MJ码哥".getBytes("GBK"));
// 可以写直接字节
fos.write(74); // M
fos.write(77); // J
fos.close();
MJ码哥MJ
FileInputStream
FileInputStream is = new FileInputStream("F:/1.txt");
// 读取第1个字节
int byte1 = is.read();
// 读取第2个字节
int byte2 = is.read();
is.close();
InputStream is = new FileInputStream("F:/2.txt");
byte[] bytes = new byte[1024];
// read返回实际读取的字节数
int len = is.read(bytes);
is.close();
练习 – 将内存中的数据写入文件
/**
* 将内存中的数据写入文件
*/
public static void write(byte[] bytes, File file){
if(bytes == null || file ==null) return;
if(file.exists()) return; // 如果文件已经存在,直接结束,不覆盖
mkparents(file);
try(FileOutputStream fos = new FileOutputStream(file)){
fos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
练习 – 从文件读取数据到内存
/**
* 将数据从文件读入到内存中
*/
public static byte[] read(File file){
if(file == null || !file.exists()) return null;
if(file.isDirectory()) return null; // 不读取文件夹
try(FileInputStream fis = new FileInputStream(file)){
byte[] bytes = new byte[(int)file.length()];
fis.read(bytes);
return bytes;
} catch (IOException e) {
e.printStackTrace();
return null;
}
};
练习 – 复制
/**
* 复制(只限于文件)
*/
public static void copy(File src, File dest){
if(src == null || dest == null) return;
if(!src.exists() || dest.exists()) return;
if(src.isDirectory()) return; // 不拷贝文件夹
mkparents(dest);
try(
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest);
){
byte[] bytes = new byte[8192];
int len;
while((len = fis.read(bytes)) != -1){
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
字符流(Character Streams)
字符流的特点:
一次只读写一个字符最终都继承自 Reader、Writer
常用的是字符流有 FileReader、FileWriter
注意:这 2 个类只适合文本文件,比如 .txt、.java 等这类文件
字符流结构预览:
FileWriter
Writer writer = new FileWriter("F:/2.txt");
writer.write('M');
writer.write('J');
writer.write('码');
writer.write('哥');
writer.close();
Writer writer = new FileWriter("F:/2.txt");
writer.write("MJ");
writer.write("码哥".toCharArray());
writer.close();
FileReader
Reader reader = new FileReader("F:/2.txt");
// 读取第1个字符
int c1 = reader.read();
// 读取第2个字符
int c2 = reader.read();
reader.close();
Reader reader = new FileReader("F:/2.txt");
char[] chars = new char[1024];
// read方法返回实际读取的字符数
int len = reader.read(chars);
reader.close();
练习 – 将文本文件的内容逐个字符打印出来
这个需求不太适合使用字节流
/**
* 练习 – 将文本文件的内容逐个字符打印出来
*/
public static void writeChar(File file){
if(file == null || file.isDirectory()) return;
try(FileReader reader = new FileReader(file)) {
int c;
while((c = reader.read()) != -1){
System.out.print((char)c);
Thread.sleep(100);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
缓冲流(Buffered Streams)
前面的字节流、字符流,都是无缓冲的 I/O 流,每个读写操作均由底层操作系统直接处理
每个读写操作通常会触发磁盘访问,因此大量的读写操作,可能会使程序的效率大大降低
为了减少读写操作带来的开销,Java 实现了缓冲的 I/O 流
缓冲输入流 从缓冲区读取数据,并且只有当缓冲区为空时才调用本地的输入 API(Native Input API)缓冲输出流 将数据写入缓冲区,并且只有当缓冲区已满时才调用本地的输出 API(Native Output API)
上述 4 个缓冲流的默认缓冲区大小是 8192 字节(8KB),可以通过构造方法传参设置缓冲区大小
缓冲流 – 使用、close、flush
缓冲流的常见使用方式:将无缓冲流传递给缓冲流的构造方法(将无缓冲流包装成缓冲流)
如果把无缓冲流比作是一个无装备的士兵,那么缓冲流就是一个有强力装备的士兵
File file = new File("F:/1.txt");
InputStream is = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(is, 16384);
bis.close();
File file = new File("F:/1.txt");
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
writer.write("111");
writer.newLine();
writer.write("222");
writer.close();
只需要执行缓冲流的 close 方法,不需要执行缓冲流内部包装的无缓冲流的 close 方法
调用缓冲输出流的 flush 方法,会强制调用本地的输出 API,将缓冲区的数据真正写入到文件中
缓冲输出流的 close 方法内部会调用一次 flush 方法
练习 - 价值百万的AI代码
标准输入流(Standard InputStream):控制台的输入、键盘的输入,System.in标准输出流(Standard OutpuStream):控制台的输出、屏幕的输出,System.out利用 InputStreamReader 可以实现 【字节输入流】转【字符输入流】同理,利用 OutputStreamWriter 可以实现 【字节输出流】转【字符输出流】
// InputStream -> InputStreamReader -> BufferedReader
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String line;
while((line = reader.readLine()) != null){
line = line.replace("你", "朕");
line = line.replace("吗", "");
line = line.replace("么", "");
line = line.replace("?", "!");
line = line.replace("?", "!");
System.out.println("\t" + line);
}
reader.close();
练习 – 用缓冲流逐个打印字符
/**
* 练习 - 缓冲流逐行打印字符串
*/
public static void writeLine(File file){
try(BufferedReader reader = new BufferedReader(new FileReader(file))){
String line;
while((line = reader.readLine()) != null){
System.out.println(line);
Thread.sleep(100);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
练习 – 转换文本文件编码
各种流的操作很灵活,方法特别多。
方法1:
File file = new File("F:/gb2312.txt");
File file2 = new File("F:/utf-8.txt");
try(
BufferedReader reader = new BufferedReader(
// 利用 InputStreamReader 将字节流转字符流
new InputStreamReader(new FileInputStream(file), "GB2312")
);
BufferedWriter writer = new BufferedWriter(
// 利用 InputStreamReader 将字节流转字符流
new OutputStreamWriter(new FileOutputStream(file2), "UTF-8")
);
){
String line;
while((line = reader.readLine()) != null){
writer.write(line);
writer.newLine();
}
}
方法2:
File file = new File("F:/gb2312.txt");
File file2 = new File("F:/utf-8.txt");
try(
BufferedReader reader = new BufferedReader(
new InputStreamReader(// 字节流转字符流
new FileInputStream(file), "GB2312"));
BufferedOutputStream writer = new BufferedOutputStream(
new FileOutputStream(file2));
){
String line;
while((line = reader.readLine()) != null){
writer.write((line + "\n").getBytes("utf-8"));
}
}
方法3:
File file = new File("F:/gb2312.txt");
File file2 = new File("F:/utf-8.txt");
try(
BufferedInputStream reader = new BufferedInputStream(
new FileInputStream(file));
BufferedOutputStream writer = new BufferedOutputStream(
new FileOutputStream(file2));
){
int len;
String string;
byte[] bytes = new byte[4196];
while((len = reader.read(bytes)) != -1){
string = new String(bytes, "gb2312");
writer.write(string.getBytes("utf-8"), 0, len);
System.out.println(string);
}
}
方法4:
File file = new File("F:/gb2312.txt");
File file2 = new File("F:/utf-8.txt");
try(
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(file), "GB2312")
);
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(file2), "UTF-8")
);
){
char[] chars = new char[1024];
int len;
while((len = reader.read(chars)) != -1){
writer.write(chars, 0, len);
}
}
Scanner
java.util.Scanner 是一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器
它默认利用空白(空格\制表符\行终止符)作为分隔符将输入分隔成多个 token
Scanner sc = new Scanner("jack rose kate");
while(sc.hasNext()){
System.out.println(sc.next());
}
sc.close();
jack
rose
kate
Scanner sc = new Scanner("jack 666 888 ak47");
System.out.println(sc.next()); // jack
System.out.println(sc.nextInt()); // 666
System.out.println(sc.nextInt()); // 888
// 利用正则表达式分隔文本
System.out.println(sc.next("[a-z]{2}\\d{2}")); // ak47
sc.close();
jack
666
888
ak47
Scanner.useDelimiter 方法可以自定义分隔符
Scannersc = new Scanner("aa 1 bb 22 cc33dd");
sc.useDelimiter("\\s*\\d+\\s*");
while(sc.hasNext()){
System.out.println(sc.next());
}
// aa bb cc dd
sc.close();
aa
bb
cc
dd
Scanner sc = new Scanner("aa11bb22cc");
sc.useDelimiter(""); // 任意字符都被分隔
while(sc.hasNext()) {
System.out.println(sc.next());
} // a a 1 1 b b 2 2 c c
sc.close();
a
a
1
1
b
b
2
2
c
c
Scanner - 标准输入流
Scannersc = new Scanner(System.in);
System.out.print("请输入第1个整数:");
int n1 = sc.nextInt();
System.out.print("请输入第2个整数:");
int n2 = sc.nextInt();
System.out.format("%d + %d = %d%n", n1, n2, n1 + n2);
sc.close();
请输入第1个整数:6
请输入第2个整数:8
6 + 8 = 14
Scanner – “价值几百万”的 AI 代码
Scanner sc = new Scanner(System.in);
while(sc.hasNextLine()){
String str = sc.nextLine();
str = str.replace("你", "朕");
str = str.replace("吗", "");
str = str.replace("么", "");
str = str.replace("?", "!");
str = str.replace("?", "!");
System.out.println("\t" + str);
}
sc.close();
格式化输出
有 2 个类可以实现格式化输出
PrintStreamPrintWriter
它们有 3 个常用方法:print、println、format
print、write 的区别
write(97) 写入的是字符 'a'print(97) 写入的是字符串 "97"
PrintStream
System.out、System.err 是 PrintStream 类型的实例
属于标准输出流(Standard Ouput Stream)比如输出到屏幕、控制台(Console)
PrintStream 是字节流,但它内部利用字符流对象来模拟字符流的许多功能
PrintWriter
平时若要创建格式化的输出流,一般使用 PrintWriter,它是字符流
String name = "Jack";
int age = 20;
PrintWriter writer = new PrintWriter("F:/1.txt");
writer.format("My name is %s,age is %d", name, age);
writer.close();
可以通过构造方法设置 PrintWriter.autoflush 为 true
那么 println、printf、format 方法内部就会自动调用 flush 方法
PrintWriter writer = new PrintWriter(
new FileOutputStream(new File("F:/1.txt")), true);
数据流(Data Streams)
有 2 个数据流:DataInputStream、DataOutputStream,支持基本类型、字符串类型的 I / O 操作
DataOutputStream 将数据写到文件当中
int age = 20;
int money = 3000;
doubleheight = 1.75;
String name = "Jack";
DataOutputStream dos = new DataOutputStream(
new FileOutputStream("F:/66.txt"));
dos.writeInt(age);
dos.writeInt(money);
dos.writeDouble(height);
dos.writeUTF(name);
dos.close();
DataInputStream 将数据从文件当中读取数据
DataInputStream dis = new DataInputStream(
new FileInputStream("F:/66.txt"));
System.out.println(dis.readInt());
System.out.println(dis.readInt());
System.out.println(dis.readDouble());
System.out.println(dis.readUTF());
dis.close();
对象流(Object Streams)、序列化(Serialization)
有 2 个对象流:ObjectInputStream、ObjectOutputStream,支持引用类型的 I / O 操作
只有实现了 java.io.Serializable 接口的类才能使用对象流进行 I / O 操作
否则会抛出 java.io.NotSerializableException 异常
Serializable 是一个标记接口(Maker Interface),不要求实现任何方法
对象的序列化和反序列化
序列化(Serialization)
将对象转换为可以存储或传输的数据利用 ObjectOutputStream 可以实现对象的序列化
反序列化(Deserialization )
从序列化后的数据中恢复出对象利用 ObjectInputStream 可以实现对象的反序列化
若将对象比作是一座冰雕
序列化:将冰雕融化成水反序列化:将融化后的水恢复成冰雕
serialVersionUID
每一个可序列化类都有一个 serialVersionUID,相当于类的版本号
默认情况下会根据类的详细信息计算出 serialVersionUID 的值,根据编译器实现的不同可能千差万别一旦类的信息发生修改,serialVersionUID 的值就会发生变化
如果序列化、反序列时的 serialVersionUID 不一致
会认定为序列化、反序列时的类不兼容,会抛出 java.io.InvalidClassException 异常
强烈建议每一个可序列化类都自定义 serialVersionUID,不要使用它的默认值
必须是 static final long建议声明为 private如果没有自定义 serialVersionUID,编译器会发出 “serial” 警告
transient
被 transient 修饰的实例变量不会被序列化
public class Dog implements Serializable {
private transient int age; // age不会被序列化
private String name;
public Dog(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Dog [age=" + age + ", name=" + name + "]";
}
}
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("F:/d.txt"));
oos.writeObject(new Dog(5, "Larry"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("F:/d.txt"));
System.out.println(ois.readObject()); // Dog [age=0, name=Larry],age没有被序列化
ois.close();
Dog [age=0, name=Larry]
练习 - 序列化与反序列化
import java.io.Serializable;
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
private double price;
private String band;
public Car(double price, String band) {
this.price = price;
this.band = band;
}
@Override
public String toString() {
return "Car [price=" + price + ", band=" + band + "]";
}
}
import java.io.Serializable;
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
private double price;
private String name;
public Book(double price, String name) {
super();
this.price = price;
this.name = name;
}
@Override
public String toString() {
return "Book [price=" + price + ", name=" + name + "]";
}
}
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private int age;
private String name;
private Car car;
private List books = new ArrayList<>();
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public List getBooks(){ return books; }
public void setCar(Car car) { this.car = car; }
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name +
", car=" + car + ", books=" + books + "]";
}
}
ObjectOutputStream – 序列化
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("F:/p.txt"));
Person p = new Person(20, "Jack");
p.setCar(new Car(305.6, "Bently"));
p.getBooks().add(new Book(19.9, "Java"));
p.getBooks().add(new Book(38.8, "C++"));
oos.writeObject(p);
Car c = new Car(107.8, "BMW");
oos.writeObject(c);
oos.close();
ObjectInputStream – 反序列化
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("F:/p.txt"));
Person p = (Person)ois.readObject();
System.out.println(p);
Car c = (Car)ois.readObject();
System.out.println(c);
ois.close();
Person [
age=20, name=Jack, car=null,
books=[Book [price=19.9, name=Java], Book [price=38.8, name=C++]]
]
Car [price=107.8, band=BMW]
Files工具类
package com.mj;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Reader;
import java.util.function.Consumer;
public class Files {
/**
* 搜索目录下的所有文件
* @param dir 目录
* @param operation 执行的操作
*/
public static void search(File dir, Consumer operation){
if(dir == null || operation == null) return;
// 目录不存在 或者 传入的是文件, 不执行操作
if(!dir.exists() || dir.isFile()) return;
File[] subfiles = dir.listFiles();
for (File sf : subfiles) {
operation.accept(sf);
if(sf.isFile()) continue; // 如果是文件,跳过,进行后面的搜索
search(sf, operation); // 如果是文件夹, 递归搜索该文件夹
}
}
/**
* 删除文件夹
* @param file
*/
public static void delete(File file){
// 传入null 或者 文件夹不存在, 不执行操作
if(file == null || !file.exists()) return;
clean(file);
file.delete();
}
/**
* 清空文件夹中文件
* @param dir
*/
public static void clean(File dir){
// 如果文件夹不存在 或者 传入的是文件, 不执行操作
if(dir == null || !dir.exists() || dir.isFile()) return;
File[] subfiles = dir.listFiles();
for (File sf : subfiles) {
delete(sf);
}
}
/**
* 剪切文件或文件夹到目标路径
*/
public static void move(File src, File dest){
if(src == null || dest == null) return;
// 如果源File不存在 或者 目标File 已经存在, 不执行操作
if(!src.exists() || dest.exists()) return;
mkparents(dest);
src.renameTo(dest);
}
/**
* 将内存中的数据写入文件
*/
public static void write(byte[] bytes, File file){
if(bytes == null || file ==null) return;
if(file.exists()) return; // 如果文件已经存在,直接结束,不覆盖
mkparents(file);
try(FileOutputStream fos = new FileOutputStream(file)){
fos.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 将数据从文件读入到内存中
*/
public static byte[] read(File file){
if(file == null || !file.exists()) return null;
if(file.isDirectory()) return null; // 不读取文件夹
try(FileInputStream fis = new FileInputStream(file)){
byte[] bytes = new byte[(int)file.length()];
fis.read(bytes);
return bytes;
} catch (IOException e) {
e.printStackTrace();
return null;
}
};
/**
* 复制(只限于文件)
*/
public static void copy(File src, File dest){
if(src == null || dest == null) return;
if(!src.exists() || dest.exists()) return;
if(src.isDirectory()) return; // 不拷贝文件夹
mkparents(dest);
try(
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest);
){
byte[] bytes = new byte[8192];
int len;
while((len = fis.read(bytes)) != -1){
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 练习 – 将文本文件的内容逐个字符打印出来
*/
public static void writeChar(File file){
if(file == null || file.isDirectory()) return;
try(FileReader reader = new FileReader(file)) {
int c;
while((c = reader.read()) != -1){
System.out.print((char)c);
Thread.sleep(100);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 练习 - 缓冲流逐行打印字符串
*/
public static void writeLine(File file){
try(BufferedReader reader = new BufferedReader(new FileReader(file))){
String line;
while((line = reader.readLine()) != null){
System.out.println(line);
Thread.sleep(100);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 创建父路径
*/
private static void mkparents(File file){
File parent = file.getParentFile();
if(parent == null) return;
parent.mkdirs();
}
}
java 数据流 中文_【Java I/O流】File、字符集、字节流、字符流、缓冲流、数据流、对象流、序列化、try-wi...相关推荐
- java截取中文_按字节截取混有中文汉字的字符串 中英文字符串截取
[java]代码库import java.io.UnsupportedEncodingException; public class CutString { /** * 判断是否是一个中文汉字 * * ...
- java aes 中文_从Java到Python的AES加密
我试图对python和java中的一些字符串进行加密和解密,反之亦然,但是当我尝试用java加密和在python中使用相同的密钥解密时,我遇到了问题.在 这是我用来解密java输出的python算法f ...
- java取负数_[Java] 告别“CV 工程师”码出高效!(基础篇)
作为一名资深的 CV 工程师,某天,当我再一次日常看见满屏的报错信息与键盘上已经磨的泛白的 Ctrl.C.V 这三个按键时,我顿悟了. 百度谷歌复制粘贴虽然很香,但是总是依靠前人种树,终会有一天失去乘 ...
- java txt中文乱码,JAVA读取TXT文件 可解决中文乱码问题
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.I ...
- java 文本压缩_[Java基础]Java使用GZIP进行文本压缩
import java.io.IOException; import java.util.zip.GZIPOutputStream; import org.apache.commons.io.outp ...
- java IO之 File类+字节流 (输入输出 缓冲流 异常处理)
1. File类 File 路径问题: 上下级文件夹之间使用分隔符分开: 在Windows中分隔符为'\' ,在Unix/Linux中分隔符为'/' 跨平台分隔符: 专业的做法是使用File.sepa ...
- Java I/O流(File、字节流、字符流、过滤流、对象流)详解
File以及I/O流 一.File类的使用 java.io.File类 代表硬盘上的一个文件或者目录 java.io.File类作用: 每个File类的对象表示一个磁盘文件或目录,其对象属性中包含了文 ...
- java drawstring 中文_centos java jdk graphics.drawString中文乱码
graphics.setColor(Color.BLACK); Font font = new Font("宋体", Font.BOLD, 40); graphics.setFon ...
- java控制语句练习题_[Java初探实例篇02]__流程控制语句知识相关的实例练习
本例就流程控制语句的应用方面,通过三个练习题来深入学习和巩固下学习的流程控制语句方面的知识,设计到,if条件判断语句,switch多分支语句,for循环语句及其嵌套多层使用,while循环语句. 练习 ...
- java resources 目录_[Java] 在 jar 文件中读取 resources 目录下的文件
注意两点: 1. 将资源目录添加到 build path,确保该目录下的文件被拷贝到 jar 文件中. 2. jar 内部的东西,可以当作 stream 来读取,但不应该当作 file 来读取. 例子 ...
最新文章
- iOS指示器之UIProgressView和UIPageControl
- jquery 总结
- 【Python基础】弄懂这几个问题,拿下 Python 生成器!
- GDCM: 简单的QIDO-RS往返测试gdcm :: JSON的实现
- FK JavaScript之:ArcGIS JavaScript API之地图动画
- python日历函数_python 怎么定义一个函数,输出日历
- C++标准转换运算符static_cast
- codeforces D. Design Tutorial: Inverse the Problem
- relativelayout常用属性
- uni-app加载中,加载结束
- dimm和udimm_服务器内存UDIMM与RDIMM区别
- python pymysql模块下载_python开发11之PyMySQL模块
- python 汉字编码
- CS231n Module2: CNN part1:Architecture
- AI读书笔记:《智能简史(谁会替代人类成为主导物种)》
- 2001-2019年290个地级市人均GDP
- 【云云怪】第3个项目:弈厢棋苑
- js关闭当前弹出的小窗口并打开新窗口
- FreeSwitch呼入处理流程
- HTML中的标记-遁地龙卷风
热门文章
- Zookeeper配置项说明
- Qt程序实现自动重启
- tensorflow-gpu_TensorFlow GPU单机多卡训练amp;reloadamp;predict
- svn 服务器修改密码,用户自行修改svn密码的简单服务
- python对比php开发web_django学习系列——python和php对比
- VideoView播放视频会引起其它音乐播放器暂停问题解决
- try-catch(C# 参考)
- Could not load file or assembly App_Licenses.dll Could not load file or assembly App_Web_
- ORACLE decode
- IE和ff下javascript解释的区别