io流
io流
1 file文件
1 file引入
1 File概念: 文件和目录路径名的抽象表示形式。
路径的抽象表现形式,这个文件可以不存在
static String pathSeparator
与系统有关的路径分隔符,为了方便,它被表示为一个字符串。
static char pathSeparatorChar
与系统有关的路径分隔符。
static String separator
与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串。
static char separatorChar
与系统有关的默认名称分隔符。
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri)
通过将给定的 file: URI 转换为一个抽象路径名来创建一个新的 File 实例。
public class FileDemo01 {
public static void main(String[] args) throws IOException {
System.out.println(File.pathSeparator); // 路径分隔符 ; 配置环境变量
System.out.println(File.pathSeparatorChar);
System.out.println(File.separator); // \ 路径名分隔符 D:\Java_0221\02_JavaSE\day02
System.out.println(File.separatorChar);
// 表示一个路径
String pathName = "D:\\Java_0221\\02_JavaSE\\day02"; // 可能针对不同的操作系统不适配
String pathName2 = "D:" + File.separator + "Java_0221"; // 可能针对不同的操作系统不适配
// 创建一个File对象
File f = new File("D:\\hello.txt"); // 创建了一个文件指针指向了D:\\hello.txt所对应的位置
// 凡是对文件的操作的第一步,必须封装文件路径
f.createNewFile();
// D:\Java_0221\02_JavaSE\day15\视频\02.ArrayList类讲解.mp4
// File(String parent, String child)
File f2 = new File("D:\\Java_0221\\02_JavaSE\\day15\\视频", "02.ArrayList类讲解.mp4");
System.out.println(f2);
// File(File parent, String child)
File f3 = new File(new File("D:\\Java_0221\\02_JavaSE\\day15\\视频"), "02.ArrayList类讲解.mp4");
System.out.println(f3);
File f4 = new File("java.txt"); // 相对于项目路径下
// D:\Java_0221\CodeLibraryForJava0221\day0318_filedemo\java.txt
System.out.println(f4.getAbsolutePath());
System.out.println(f4.createNewFile());
}
}
2 file 的创建
文件的创建
public boolean createNewFile() 若文件不存在则创建新文件
public boolean mkdir() 创建目录
public boolean mkdirs() 创建目录及不存在的父目录
注意
1.操作文件第一步一定创建文件指针指向对应文件位置
2.如果需要对某一个文件进行操作,那么改文件的父路径一定要存在
public class FileDemo02 {
public static void main(String[] args) throws IOException {
// 在项目文件夹下面创建一个a.txt
File f1 = new File("a.txt");
System.out.println("createNewFile: " + f1.createNewFile());
// 在项目文件夹filedemo下面创建一个a.txt
File f2 = new File("src/com/sxt/filedemo/a.txt");
System.out.println("createNewFile: " + f2.createNewFile());
// File f3 = new File("X:/a.txt");
// System.out.println("createNewFile: " + f3.createNewFile());
// 在项目路径下创建aaa文件夹
File f4 = new File("aaa");
System.out.println(f4.mkdir());
// 在项目路径下创建 bbb/a.txt
File f5 = new File("bbb");
File f6 = new File(f5,"x.txt");
System.out.println(f5.mkdir());
System.out.println(f6.createNewFile());
// 在项目路径下创建 xxx/yyy/zzz/haha.txt
// File f7 = new File("xxx");
// File f8 = new File("xxx/yyy");
// File f9 = new File("xxx/yyy/zzz");
// File f10 = new File("xxx/yyy/zzz/haha.txt");
// System.out.println(f7.mkdir());
// System.out.println(f8.mkdir());
// System.out.println(f9.mkdir());
// System.out.println(f10.createNewFile());
File f11 = new File("xxx/yyy/zzz");
File f12 = new File(f11, "haha.txt");
System.out.println(f11.mkdirs());
System.out.println(f12.createNewFile());
}
}
3 file的删除
文件的删除
1.public boolean delete() 删除文件及空目录
只能一步一步的删除 如下代码
2.递归删除
删除带内容文件夹需要使用递归删除,
public class FileDemo03 {
public static void main(String[] args) {
File f1 = new File("xxx/yyy/zzz/haha.txt");
File f2 = new File("xxx/yyy/zzz");
File f3 = new File("xxx/yyy");
File f4 = new File("xxx");
System.out.println(f1.delete());
System.out.println(f2.delete());
System.out.println(f3.delete());
System.out.println(f4.delete());
}
}
4 file的重命名
文件的重命名
public boolean renameTo(File dest) 重命名为dest
如果源文件和目标文件父路径保持一致,表示更名
如果源文件和目标文件父路径不一致,表示先剪切然后更名
public class FileDemo04 {
public static void main(String[] args) {
// 将java.txt修改成android.txt
File f = new File("java.txt");
File dest = new File("android.txt");
System.out.println(f.renameTo(dest));
// 将android.txt修改成 php.txt
File f2 = new File("android.txt");
File dest2 = new File("src/com/sxt/filedemo/php.txt");
System.out.println(f2.renameTo(dest2));
}
}
5 file 的相关属性功能
文件的相关属性功能
public boolean isFile() 是否文件
public boolean isDirectory() 是否目录
public boolean canRead() 是否可读
public boolean canWrite() 是否可写
public boolean exists() 是否存在
public boolean isHidden() 是否隐藏
public long length() 长度
public String getAbsolutePath() 绝对路径
public String getPath() 定义的路径
public String getName() file名字
public long lastModified() 最后一次修改时间
public class FileDemo05 {
public static void main(String[] args) {
File f = new File("a.txt");
System.out.println("isFile:" + f.isFile());
System.out.println("isDirectory:" + f.isDirectory());
System.out.println("canRead:" + f.canRead());
System.out.println("canWrite:" + f.canWrite());
System.out.println("exists:" + f.exists());
System.out.println("isHidden:" + f.isHidden());
System.out.println("length:" + f.length());
System.out.println("getAbsolutePath:" + f.getAbsolutePath());
System.out.println("getPath:" + f.getPath());
System.out.println("getName:" + f.getName());
System.out.println("lastModified:" + f.lastModified());
char ch = '\n';
char ch2 = '\r';
String ch3 = "\r\n";
Date d = new Date(1552892143776L);
System.out.println(d);
Calendar c = Calendar.getInstance();
c.setTimeInMillis(1552892143776L);
System.out.format("现在是北京时间%d/%s/%d %d:%d:%d",c.get(Calendar.YEAR),
((c.get(Calendar.MONTH) + 1 < 10) ? "0" + (c.get(Calendar.MONTH) + 1) : c.get(Calendar.MONTH) + 1),c.get(Calendar.DAY_OF_MONTH)
,c.get(Calendar.HOUR), c.get(Calendar.MINUTE), c.get(Calendar.SECOND));
}
}
6 文件的遍历
文件的遍历
public String[] list() 返回file下的文件和目录名称(字符串)
public File[] listFiles() 返回file下的文件和目录(文件)
public String[] list(FilenameFilter filter) 根据filter过滤返回file下文件和目录名称
public File[] listFiles(FileFilter filter) 根据filter过滤返回file下文件和目录
public class FileDemo06 {
public static void main(String[] args) {
// 希望遍历com.sxt.filedemo目录下的所有文件
File f1 = new File("src/com/sxt/filedemo");
/*String[] fileNames = f1.list();
for (String fileName : fileNames) {
System.out.println(fileName);
}
System.out.println("================");
File[] files = f1.listFiles();
for (File f : files) {
System.out.println(f.getAbsolutePath() + "|" + f.length());
}*/
// 希望遍历com.sxt.filedemo目录下的所有的Java文件
/*String[] fileNames = f1.list(new FilenameFilter() {
// 写一个接口 参数列表 返回值类型 方法名
// 利用返回值去继续往下写我的需求
@Override
public boolean accept(File f, String name) {
// System.out.println(f + "|" + name);
File file = new File(f, name);
if (file.getName().endsWith(".java")) {
return true;
} else {
return false;
}
}
});
for (String fileName : fileNames) {
System.out.println(fileName);
}*/
File[] files = f1.listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isFile() && f.getName().endsWith(".java");
}
});
for (File file : files) {
System.out.println(file.getAbsolutePath());
}
}
}
7 递归的批量操作
批量操作 (递归)
批量创建
批量删除
批量修改
批量查询
递归:
1.必须存在方法,自己调自己
2.递归必须要有出口,否则容易出现死递归
1 批量查找文件如下
/*需求: 获取D:\Java_0221\CodeLibraryForJava0221文件夹下面所有的Java文件
分析:
1.封装文件路径指向需要操作的文件位置 D:\Java_0221\CodeLibraryForJava0221
2.获取该目录下所有的文件或者文件夹
3.获取到每一个文件或者文件夹
4.判断该对象是文件还是文件夹 (if-else)
是文件
判断该文件是否以后缀名.java结尾 (单if)
是
输出文件名称
否
不处理
是文件夹
回到第2步
*/
public class BatchFileDemo01 {
public static void main(String[] args) {
// 1.封装文件路径指向需要操作的文件位置 D:\Java_0221\CodeLibraryForJava0221
File srcFile = new File("D:\\Java_0221\\CodeLibraryForJava0221");
getAllJavaFile(srcFile);
}
public static void getAllJavaFile(File srcFile) throws NullPointerException {
if (srcFile == null) {
throw new NullPointerException("传入的文件对象不能为null!!!");
}
// 2.获取该目录下所有的文件或者文件夹
File[] files = srcFile.listFiles();
// 3.获取到每一个文件或者文件夹
if (files != null && files.length != 0) {
for (File f : files) {
// 4.判断该对象是文件还是文件夹 (if-else)
if (f.isDirectory()) {
// 回到第2步
getAllJavaFile(f);
} else {
// 判断该文件是否以后缀名.java结尾 (单if)
String fileName = f.getName();
if (fileName.endsWith(".java")) {
// 输出文件名称
System.out.println(fileName);
}
}
}
}
}
}
**2 批量查找视屏文件 **如下
/*统计视频文件的个数
* D:\Java_0221
*/
public class BatchFileDemo02 {
public static int mp4FileCount = 0;
public static List<File> list = new ArrayList<File>();
public static void main(String[] args) {
System.out.println("MP4文件的个数是: " + getAllMp4FileCount(new File("D:\\Java_0221\\02_JavaSE")));
for (File f : list) {
System.out.println(f.getName());
}
}
public static int getAllMp4FileCount(File srcFile) {
if (srcFile == null) {
throw new NullPointerException("传入的文件对象不能为null!!!");
}
File[] files = srcFile.listFiles();
if (files != null && files.length != 0) {
for (File f : files) {
if (f.isDirectory()) {
getAllMp4FileCount(f);
} else {
String fileName = f.getName();
if (fileName.endsWith(".mp4")) {
mp4FileCount ++;
list.add(f);
}
}
}
}
return mp4FileCount;
}
}
3 批量删除如下
/*
* 批量删除
* D:\Java_1227\day01
* 思路:
* 1.封装文件指针指向需要操作的文件位置
* 2.遍历到源路径下所有的文件或者文件夹
* 3.获取到每一个文件或者文件夹
* 4.判断该对象是文件还是文件夹
* 是文件夹
* 回到第二步
* 是文件
* 直接删除
* 5.删除空目录
*/
public class BatchFileDemo03 {
public static void main(String[] args) {
// 1.封装文件指针指向需要操作的文件位置
File srcFile = new File("D:\\Java_1227\\day01");
try {
deleteFolder(srcFile);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void deleteFolder(File srcFile) throws NullPointerException {
if (srcFile == null) {
throw new NullPointerException("传入的文件不能为null");
}
// 2.遍历到源路径下所有的文件或者文件夹
File[] files = srcFile.listFiles();
// 3.获取到每一个文件或者文件夹
if (files != null && files.length != 0) {
for (File f : files) {
// 4.判断该对象是文件还是文件夹
if (f.isDirectory()) {
deleteFolder(f);
} else {
System.out.println("\t删除文件:" + f.getName() + ":" + (f.delete() ? "成功" : "失败"));
}
}
}
// 5.删除空目录
System.out.println("删除文件夹:" + srcFile.getName() + ":" + (srcFile.delete() ? "成功" : "失败"));
}
}
2 io
1 io 的引入
IO流的本质
用于数据的传输
IO流的分类
1 按照数据类型分类
字节流
字符流
2 按照流向分类
输入流
输出流
3 流向:
内存 -> 外界 输出流
外界 -> 内存 输入流
4 分类
字节流
字节输入流 XXXInputStream
字节输出流 XXXOutputStream
字符流
字符输入流 XXXReader
字符输出流 XXXWriter
流的三要素
1.数据源:数据从哪里到内存
2.目的地:数据从内存到哪里
3.交通工具:选择IO流框架中对应的输入流或者输出流来处理
处理对象
字节流: 主要用来处理字节或二进制对象。例如 视频 音频 图片
字符流: 主要用来处理字符、字符数组或字符串文件 例如 html css txt js xml json
字节流是万能流,能够处理任何文件,但是在处理字符方面不太方便,所以有字符流
2 字节流
1. OutputStream (io字节流的输出) 抽象的
方法
void close()
关闭此输出流并释放与此流有关的所有系统资源。
void flush()
刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
将指定的字节写入此输出流。
Exception in thread “main” java.io.IOException: Stream Closed
流已经关闭了就不能够再次使用了
// 需求:向文本里写入“HelloWorld”。
// 注意:
// 1.IO流的创建会默认创建文件
public class IODemo02 {
public static void main(String[] args) throws IOException {
/*
* 数据源: 内存
* 目的地: 文本文件 a.txt
* 交通工具: 选择输出流 OutputStream
* FileOutputStream(File file)
*/
String s = "HelloWorld";
File f = new File("D://qwe/a.txt");
OutputStream os = new FileOutputStream(f);
byte[] bys = s.getBytes(); // 编码的方法
// os.write(bys);
// os.write(bys, 5, 5);
// os.write(97);
os.write("97".getBytes());
os.flush();
os.close();
// os.write(100);
}
}
构造方法
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。
注意:
1.换行符在不同的操作系统中不适配
windows \r\n
linux \n
max \r
所以字节流在某些时候在操作字符或者字符数组或者字符串不方便,后面字符流可简单处理
2.追加写入 append参数
3.IO流中加入异常处理
public class IODemo03 {
public static void main(String[] args) throws Exception {
OutputStream os = new FileOutputStream("b.txt", true);
// os.write("Hello".getBytes());
for (int i = 1; i <= 10; i++) {
os.write(("HelloWorld" + i).getBytes());
os.write("\r\n".getBytes());
os.flush();
}
os.close();
}
}
2 Inputstream(io字节流的输入) 抽象的
需求:将文本文件的数据读取出来显示在控制台
InputStream
FileInputStream
FileInputStream的构造方法
FileInputStream(File file) 创建一个从file读取数据的输入流
FileInputStream(String name) 创建一个从name文件读取数据的输入流
FileInputStream的成员方法
注意:
1.使用输出流的时候,如果文件不存在,系统会帮我们自动创建
2.使用输入流的时候,文件必须存在
public class IODemo01 {
public static void main(String[] args) throws Exception {
/*
* 数据源: 文本文件
* 目的地: 控制台
* 交通工具:
* 文本文件 -> 内存 输入流
* 内存 -> 控制台 输出流 暂时不需要考虑 System.out.println();
*/
InputStream is = new FileInputStream("is.txt");
String s = "中国";
System.out.println(Arrays.toString(s.getBytes()));
int by = 0;
while((by = is.read()) != -1) {
System.out.print((char)by);
}
}
}
int read() 一次读取一个字节
1.每次读取一个字节
2.每读取一个字节,指针向后移动一个字节单位
3.读到文件末尾返回-1
4.一次性读取一个字节存在的问题: 如果是中文或者其他文字会出现乱码
方案一:处理一些字符不太方便,建议使用字符流
方案二:或者一次性不要读取一个字节
int read(byte[] b) 一次读取一个字节数组
int read(byte[] b, int off, int len) 一次读取一个字节数组的一部分 基本不用
void close() 关闭此文件输入流并释放与此流有关的所有系统资源
/*
* int read(byte[] b) 一次读取一个字节数组
* 1.每次读取一个字节数组,读取出来保存到形参定义的字节数组中
* 2.返回的是每次读取的实际长度
*/
public class IODemo02 {
public static void main(String[] args) throws Exception {
File f = new File("jys.txt");
FileInputStream fis = new FileInputStream(f);
// 标准写法
int len = 0;
byte[] bys = new byte[1024];
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
}
}
3 .io流异常处理
/*
* 练习: 写一首诗到文件中 数据源来自于集合
*/
public class IODemo05 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("窗前明月光");
list.add("疑似地上霜");
list.add("举头望明月");
list.add("低头思故乡");
/*
* 数据源: 内存中的集合
* 目的地: 文件
* 交通工具: 内存->文件 FileOutputStream
*/
FileOutputStream fos = null;
try {
fos = new FileOutputStream("jys.txt");
for (String poem : list) {
fos.write((poem + "\r\n").getBytes());
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("Over");
}
}
4 字节流拷贝文件
第一种方式
一次性读取一个字节数组拷贝文件
public class IODemo03 {
public static void main(String[] args) {
copyFile1("D:\\Java_0221\\02_JavaSE\\day06\\视频\\01.方法的重载.mp4", "haha.mp4");
}
// 一次性读取一个字节数组拷贝文件
public static void copyFile2(String srcFile, String descFile) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(descFile);
int len = 0;
byte[] bys = new byte[1024];
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
第二种方式
一次性读取一个字节拷贝文件
/*
* 数据源: 文件
* 目的地: 文件
* 交通工具
* 文件 -> 内存 输入流 FileInputStream
* 内存 -> 文件 输出流 FileOutputStream
*/
public class IODemo03 {
public static void main(String[] args) {
copyFile2("D:\\Java_0221\\02_JavaSE\\day06\\视频\\01.方法的重载.mp4", "haha.mp4");
}
public static void copyFile(String srcFile, String descFile) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(descFile);
int b = 0;
while ((b = fis.read()) != -1) {
fos.write(b);
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
5 字节缓冲输入流和输出流
字节流一次读写一个字节数组,
大小为1024的速度明显比一次读写一个字节的速度要快的多的多,
因为这里加入了数组缓冲区的思想,
Java考虑到流读写效率的提升所以为我们提供了字节缓冲流。
字节缓冲输出流
BufferedOutputStream
字节缓冲输入流
BufferedInputStream
代码演示加入字节缓冲流之后的视频拷贝的效率区别
public class IODemo04 {
public static void main(String[] args) throws Exception {
// write();
// read();
long start = System.currentTimeMillis();
// copyFile2("D:\\Java_0221\\02_JavaSE\\day06\\视频\\01.方法的重载.mp4", "haha.mp4");// 231
// copyFile3("D:\\Java_0221\\02_JavaSE\\day06\\视频\\01.方法的重载.mp4", "hehe.mp4");// 718
copyFile("jys.txt", "jys4.txt");// 718
long end = System.currentTimeMillis();
System.out.println(end - start);
}
// 一次性读取一个字节拷贝文件
/*
* 数据源: 文件 目的地: 文件 交通工具 文件 -> 内存 输入流 FileInputStream 内存 -> 文件 输出流
* FileOutputStream
*/
public static void copyFile(String srcFile, String descFile) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(descFile);
int b = 0;
while ((b = fis.read()) != -1) {
fos.write(b);
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
// 一次性读取一个字节数组拷贝文件
public static void copyFile2(String srcFile, String descFile) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(descFile);
int len = 0;
byte[] bys = new byte[8192];
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
fos.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*
* 使用高效缓冲读取一个字节
*/
public static void copyFile3(String srcFile, String descFile) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFile));
int len = 0;
byte[] bys = new byte[1024];
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
bis.close();
bos.close();
}
public static void read() throws FileNotFoundException, IOException {
InputStream is = new FileInputStream("bis.txt");
BufferedInputStream bis = new BufferedInputStream(is);
byte[] bys = new byte[10];
int len = is.read(bys);
System.out.println(new String(bys, 0, len));
bis.close();
}
public static void write() throws FileNotFoundException, IOException {
OutputStream os = new FileOutputStream("bos.txt");
BufferedOutputStream bos = new BufferedOutputStream(os);
bos.write("hello".getBytes());
bos.flush();
bos.close();
}
}
3 乱码现象
计算机是如何进行编码 解码的?
编码
文本信息 -通过编码表-> 十进制 --> 二进制 --> 传输
解码
二进制 --> 十进制 -通过编码表-> 文本信息
编码表:
ASCII 美国标准信息交换码 1个字节存储一个字符
Unicode 国际标准码 2个字节储存储字符 0~65535 前0~256正好和ASCII码表兼容
UTF-8 最多用三个字节来表示一个字符。 目前项目最常用的编码表
ISO-8859-1 拉丁码表。欧洲码表。 不支持中文的 Tomcat7包括之前的服务器版本/FTP服务器都是使用这个编码
GB2312/GBK/GB18030 中文编码表。 Java平台中默认采用的编码方式是GBK。
系统支持的编码有哪些?
1.字符编码解码 char ch = ‘a’;
2.字符串编码解码 getBytes(String charsetName) new String(byte[] bys, String charsetName)
3.流的编码解码 OutputStreamWriter InputStreamReader
计算机是如何处理中文的?
计算处理中文的流程
首先判断当前这个字符是英文还是中文
英文是整数,中文是负数
如果是英文
就查找当前系统的编码表,根据编码表转换成对应的字符
如果是中文
就查找当前系统的编码表
如果是GBK,就等待下一个字节拼接组成一个字符
如果是UTF-8,就等待下两个字节拼接组成一个字符
乱码原因有哪些?
1.人为的转换
2.编码和解码使用的编码表不一致
3.可能和系统编码产生冲突 (Tomcat7是ISO-8859-1,Tomcat8是UTF-8)
4.考虑浏览器编码,浏览器会使用URL编码 讲解Tomcat服务器讲解
4 字符流
1 字符流的引入
为什么引入字符流?因为字节流有如下缺点:
1.处理换行符不方便
2.处理编码不方便
3.处理中文不方便
4.读取一行不方便
需求:使用字符流向文本里写入“HelloWorld”。
Writer(抽象类,不能直接使用,选择子类)
OutputStreamWriter(转换流,是字符流通向字节流的桥梁,可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认字符集编码。)
构造方法
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的字符输出转换流
OutputStreamWriter(OutputStream out, Charset cs) 创建使用cs字符集的字符输出转换流
OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用enc字符集编码器的
OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的
其他方法
Writer append(char c)
将指定字符添加到此 writer。
Writer append(CharSequence csq)
将指定字符序列添加到此 writer。
Writer append(CharSequence csq, int start, int end)
将指定字符序列的子序列添加到此 writer.Appendable。
abstract void close()
关闭此流,但要先刷新它。
abstract void flush()
刷新该流的缓冲。
void write(char[] cbuf)
写入字符数组。
abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
void write(int c)
写入单个字符。
void write(String str)
写入字符串。
void write(String str, int off, int len)
写入字符串的某一部分。
public class IODemo02 {
public static void main(String[] args) throws Exception {
// write();
// write2();
write3();
}
public static void write3() throws Exception{
Writer w = new OutputStreamWriter(new FileOutputStream("osw.txt"));
// w.append("abc").append("123").append("hello");
// w.write(97);
w.write(new char[] {'a','b','c'});
w.flush();
w.close();
}
public static void write2() throws UnsupportedEncodingException, FileNotFoundException, IOException {
String s = "HelloWorld中国";
Writer w = new OutputStreamWriter(new FileOutputStream("osw.txt"), "UTF-8");
w.write(s);
w.flush();
w.close();
}
private static void write() throws FileNotFoundException, IOException {
String s = "HelloWorld";
Writer w = new OutputStreamWriter(new FileOutputStream("w.txt"));
w.write(s);
w.flush();
w.close();
}
}
2 字符流拷贝文件
方式一
字节流可以处理所有文件,但是文本文件建议使用字符流
字符流只能够处理文本文件,不能够处理二进制文件
public class IODemo04 {
public static void main(String[] args) throws Exception {
copy("D:\\Java_0221\\02_JavaSE\\day06\\视频\\01.方法的重载.mp4", "ok.mp4");
}
public static void copy(String srcFile, String descFile) throws Exception{
Reader r = new InputStreamReader(new FileInputStream(srcFile));
Writer w = new OutputStreamWriter(new FileOutputStream(descFile));
int len = 0;
char[] chs = new char[1024];
while ((len = r.read(chs))!=-1) {
w.write(chs, 0, len);
w.flush();
}
r.close();
w.close();
}
}
方式二
FileWriter:
用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个OutputStreamWriter。
FileReader:
用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
构造方法类似FileInputStream和FileOutputStream
成员方法完全继承自父类OutputStreamWriter和InputStreamReader
代码演示使用FileWriter和FileReader复制文件内容
public class IODemo05 {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("IODemo03.java");
FileWriter fw = new FileWriter("demo.java");
int len = 0;
char[] chs = new char[1024];
while ((len = fr.read(chs))!=-1) {
fw.write(chs, 0, len);
fw.flush();
}
fr.close();
fw.close();
}
}
3 字符缓冲流
类似于字节流的BufferedOutputStream和BufferedInputStream,字符流同样存在字符字符缓冲流
同理,字符缓冲流也是为了提高字符流的效率。
BufferedWriter和BufferedReader继承自Writer和Reader,所以具备原有的读取方法,但是还存在自己特有的方法。
特有的方法:
BufferedWriter:void newLine()
BufferedReader:String readLine()
代码演示字符缓冲流拷贝文件内容
字节流: BufferedInputStream + BufferedOutputStream
字符流: BufferedReader + BufferedWriter
public class IODemo06 {
public static void main(String[] args) throws Exception {
// write();
// read();
copy();
}
public static void copy() throws Exception {
BufferedReader br = new BufferedReader(new FileReader("IODemo03.java"));
BufferedWriter bw = new BufferedWriter(new FileWriter("Hello.txt"));
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
public static void read() throws Exception{
BufferedReader br = new BufferedReader(new FileReader("IODemo01.java"));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
private static void write() throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
bw.write("Hello");
bw.newLine();
bw.flush();
bw.write("World");
bw.newLine();
bw.flush();
bw.write("Java");
bw.newLine();
bw.flush();
bw.close();
}
}
上一篇: IO流操作文件相关方法(二)
下一篇: 【Swift】图片裁剪