本文最后更新于:1 年前
IO流-1
1. File
1.1 概述
File对象主要是用来表示文件或者是目录的路径的。类中提供了很多对文件或者文件夹操作的常用方法。
1.2 创建对象
1 2 3
| File(String pathname) File(String parent, String child) File(File parent, String child)
|
1.3 常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| boolean createNewFile() boolean mkdir() boolean mkdirs()
boolean exists() boolean isFile() boolean isDirectory() boolean delete() long length()
String getName() File getParentFile() String getAbsolutePath()
|
1.4 重要方法
注意:如果不是文件夹或者是文件夹的权限受限返回值是null。所以一定要对返回结果做非空判断。
1 2 3 4 5 6 7 8 9
| public static void main(String[] args) { File dir = new File("C:\\Users\\root\\Desktop\\test\\a.txt"); File[] files = dir.listFiles(); if(files!=null){ for (File file : files) { System.out.println(file); } } }
|
2. 递归
在方法中调用方法本身就是递归。
例如
1 2 3 4 5 6
| public int f(int n){ if(n==1){ return 1; } return n*f(n-1); }
|
注意:我们在使用递归的过程中一定要保证递归能结束,不能无限递归下去不然会出现栈溢出(StackOverflowError)的情况 。
小结:如果既可以用递归解决又可以用循环解决。我们一般用循环解决。
IO流-2
1. IO流概述
当需要进行数据的传输的时候可以使用IO流来进行。例如:把磁盘中文件的数据读取到内存中。把内存中的数据写入到磁盘中。把网络中的数据读取到内存中。
2. IO流分类
IO流根据处理数据类型的不同分为字符流和字节流,根据数据流向不同分为输入流和输出流,对输入流只能进行读操作,对输出流只能进行写操作。
数据类型 |
流向 |
顶层父类 |
字节流 |
输入(读) |
java.io.InputStream |
字节流 |
输出(写) |
java.io.OutputStream |
字符流 |
输入(读) |
java.io.Reader |
字符流 |
输出(写) |
java.io.Writer |
3. 字节输入流
所有字节输入流的父类是 java.io.InputStream ,它是以字节为单位的输入流 。
我们就以FileInputStream为例进行学习。
FileInputStream是用来读取文件数据的字节输入流。
构造方法如下:
1 2
| FileInputStream(String name) throws FileNotFoundException FileInputStream(File file) throws FileNotFoundException
|
范例:
1 2 3 4 5 6 7 8 9
| public static void main(String[] args) throws FileNotFoundException { FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); System.out.println(fis);
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileInputStream fis2 = new FileInputStream(file); System.out.println(fis); }
|
3.3 读取数据
我们可以使用FileInputStream来读取文件中的字节数据。
3.3.1 一次读取一个字节
核心方法如下:
1
| public int read() throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); int b; while((b=fis.read())!=-1){ System.out.println(b); } fis.close(); }
|
3.3.2 一次读取一个字节数组
核心方法如下:
1
| public int read(byte b[]) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); byte[] bytes = new byte[1024*2]; int len; while ((len=fis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); } fis.close(); }
|
3.4 资源释放
我们在前面处理异常的时候都同意做了声明抛出的处理。但是这很可能导致在出现了异常时资源没有被正确的释放。所以我们要更合理的处理异常,尤其是处理资源释放的问题。
3.4.1 JDK6版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private static void test() { FileInputStream fis = null; try{ fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); byte[] bytes = new byte[1024*2]; int len; while ((len=fis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); } }catch (IOException e){ e.printStackTrace(); }finally { if(fis!=null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } }
} }
|
3.4.2 JDK7版本
可以使用try…catch…resource的写法,在try的后面可以加小括号,把需要释放的资源在小括号中定义。我们就不需要自己去释放资源,jvm会帮我们再最后调用close方法释放资源的。
1 2 3 4 5 6 7 8 9 10 11 12
| private static void test2() { try(FileInputStream fis =new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); ){ byte[] bytes = new byte[1024*2]; int len; while ((len=fis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); } }catch (IOException e){ e.printStackTrace(); } }
|
3.4.3 JDK9版本
资源的定义也可以不放在try的小括号中,只要在try的小括号中声明要释放的资源即可。
1 2 3 4 5 6 7 8 9 10 11 12 13
| private static void test3() throws FileNotFoundException { FileInputStream fis =new FileInputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); try(fis ){ byte[] bytes = new byte[1024*2]; int len; while ((len=fis.read(bytes))!=-1){ System.out.println(new String(bytes,0,len)); } }catch (IOException e){ e.printStackTrace(); } }
|
4. 字节输出流
所有字节输出流的父类是 java.io.OutputStream ,它是以字节为单位的输出流 。
我们就以FileOutputStream为例进行学习。
4.1 FileOutputStream概述
FileOutputStream是用来往文件中写入数据的字节输出流。
4.2 FileOutputStream对象创建
常用构造方法如下:
1 2
| FileOutputStream(String name) throws FileNotFoundException FileOutputStream(File file) throws FileNotFoundException
|
示例:
1 2 3 4 5
| public static void main(String[] args) throws FileNotFoundException { FileOutputStream fos = new FileOutputStream("C:\\Users\\root\\Desktop\\test\\11.txt"); File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileOutputStream fos2 = new FileOutputStream(file); }
|
4.3 写数据
我们可以使用FileOutputStream来往文件中写入字节数据。
4.3.1 一次写一个字节
核心方法如下:
1
| public void write(int b) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9
| public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileOutputStream fos = new FileOutputStream(file);
fos.write('a');
fos.close(); }
|
4.3.2 一次写一个字节数组
核心方法如下:
1 2
| public void write(byte b[]) throws IOException public void write(byte b[], int off, int len) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12
| public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileOutputStream fos = new FileOutputStream(file);
byte[] bytes = "abc".getBytes();
fos.write(bytes,0,2);
fos.close(); }
|
4.4文件续写
如果用之前的构造方法创建的流对象,每次流对象创建的时候就会把文件中的内容情况。所以没有办法实现续写的效果。如果需要续写就需要使用另外的构造方法。
1 2
| FileOutputStream(String name, boolean append) throws FileNotFoundException FileOutputStream(File file, boolean append) throws FileNotFoundException
|
使用什么的构造创建流对象,并且第二个参数传入true,就不会清空文件中原有的内容。实现文件续写的效果。
范例:
1 2 3 4 5 6 7 8 9 10 11 12
| public static void main(String[] args) throws IOException {
File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileOutputStream fos = new FileOutputStream(file,true);
byte[] bytes = "abc".getBytes();
fos.write(bytes,0,2);
fos.close(); }
|
5.练习
5.1 文件复制
要求定义一个方法,该方法能够实现文件的复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public static void main(String[] args) throws IOException {
File src = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); File destDir = new File("C:\\Users\\root\\Desktop\\test\\a"); copyFile(src,destDir); }
public static void copyFile(File srcFile,File destDir) throws IOException { File destFile = new File(destDir,srcFile.getName()); FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile);
byte[] bytes = new byte[1024]; int len; while((len=fis.read(bytes))!=-1){ fos.write(bytes,0,len); } fis.close(); fos.close();
}
|
5.2 文件夹复制
要求定义一个方法,该方法能够实现文件夹的复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| public class Test09 { public static void main(String[] args) throws IOException { File srcDir = new File("C:\\Users\\root\\Desktop\\test"); File dest = new File("C:\\Users\\root\\Desktop\\test2"); copyDir(srcDir,dest); }
public static void copyDir(File srcDir,File dest ) throws IOException { if(!(srcDir.exists()&&srcDir.isDirectory())){ throw new RuntimeException("源文件夹必须存在并且是一个文件夹"); } if(!dest.isDirectory()){ throw new RuntimeException("目标文件夹必须是一个文件夹"); } File destDir = new File(dest,srcDir.getName()); destDir.mkdirs(); File[] files = srcDir.listFiles(); if(files!=null){ for (File file : files) { if(file.isFile()){ copyFile(file,destDir); }else { copyDir(file,destDir); }
} }
}
public static void copyFile(File srcFile,File destDir) throws IOException { File destFile = new File(destDir,srcFile.getName()); FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile);
byte[] bytes = new byte[1024]; int len; while((len=fis.read(bytes))!=-1){ fos.write(bytes,0,len); } fis.close(); fos.close();
} }
|
IO流-3
1.编码表
计算机要准确的存储和识别各种字符集符号,就需要进行字符编码,一套字符集必然至少有一套字符编码。 如果**编码和解码不是用一个编码表**就会出现**乱码**问题。
编码(加密):把看懂的–>看不懂
解码(解密):看不懂–>把看懂的
1.1 常见的编码表
ASCII
用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)
基本的ASCII字符集,使用7位表示一个字符,共128字符。ASCII的扩展字符集使用8位表示一个字符,共256字符,方便支持欧洲常用字符。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等
GBK
最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
Unicode
UTF-8编码:可以用来表示Unicode标准中任意字符,它是电子邮件、网页及其他存储或传送文字的应用 中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。它使用一至四个字节为每个字符编码
编码规则:
128个US-ASCII字符,只需一个字节编码
拉丁文等字符,需要二个字节编码
大部分常用字(含中文),使用三个字节编码
其他极少使用的Unicode辅助字符,使用四字节编码
ANSI
其实不是具体的编码表,它指代系统的默认编码表。例如:简体中文的Windows系统默认编码是GBK。
2. 字符流
当需要读取/写入的数据是纯文本的形式时我们可以使用字符流来进行操作会更加方便。
2.1 字符输入流
所有字符输入流的父类是 java.io.Reader ,它是以字符为单位的输入流 。
我们就以其子类FileReader为例进行学习。
2.1.1 FileReader 概述
FileReader 是用来从文件中读取数据的字符输入流。
2.1.2 FileReader创建对象
构造方法如下:
1 2
| public FileReader(String fileName) throws FileNotFoundException public FileReader(File file) throws FileNotFoundException
|
范例:
1 2 3 4 5 6
| public static void main(String[] args) throws FileNotFoundException {
FileReader fr = new FileReader("C:\\Users\\root\\Desktop\\test\\汉字2.txt");
FileReader fr2 = new FileReader(new File("C:\\Users\\root\\Desktop\\test\\汉字2.txt")); }
|
2.1.3 读取数据
2.1.3.1 一次读取一个字符
核心方法如下:
1
| public int read() throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static void main(String[] args) throws IOException { FileReader fr = new FileReader(new File("C:\\Users\\root\\Desktop\\test\\11.txt"));
int ch; while((ch=fr.read())!=-1){ System.out.println((char)ch); }
fr.close(); }
|
2.1.3.2 一次读取一个字符数组
核心方法如下:
1
| public int read(char cbuf[]) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws IOException {
FileReader fr = new FileReader(new File("C:\\Users\\root\\Desktop\\test\\11.txt"));
char[] chars = new char[1024]; int len; while((len=fr.read(chars))!=-1){ System.out.println(chars); } fr.close(); }
|
2.2 字符输出流
所有字符输出流的父类是 java.io.Writer ,它是以字符为单位的输出流 。
我们就以FileWriter为例进行学习。
2.2.1 FileWriter概述
FileWriter是用来往文件写入数据的字符输出流。
2.2.2 FileWriter对象创建
构造方法如下:
1 2
| public FileWriter(String fileName) throws IOException public FileWriter(File file) throws IOException
|
范例:
1 2 3 4 5 6
| public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("C:\\Users\\root\\Desktop\\test\\11.txt");
FileWriter fw2 = new FileWriter(new File("C:\\Users\\root\\Desktop\\test\\11.txt")); }
|
2.2.3 写入数据
2.2.3.1 一次写一个字符
核心方法如下:
1 2
| public void write(int c) throws IOException public void flush() throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter(new File("C:\\Users\\root\\Desktop\\test\\11.txt"));
fw.write('三'); fw.write('更'); fw.flush(); fw.write('草'); fw.write('堂'); fw.close(); }
|
2.2.3.2 一次写一个字符数组
核心方法如下:
1
| public void write(char cbuf[]) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter(new File("C:\\Users\\root\\Desktop\\test\\11.txt"));
char[] chars = "三更".toCharArray(); fw.write(chars);
fw.flush();
chars = "草堂".toCharArray(); fw.write(chars);
fw.close(); }
|
2.2.3.3 一次写一个字符串
核心方法如下:
1
| public void write(String str) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter(new File("C:\\Users\\root\\Desktop\\test\\11.txt"));
fw.write("三更草堂"); fw.flush();
fw.close(); }
|
2.2.3.4 如何抉择?
随机应变,有什么类型的数据就使用对应的重载。
练习
1.使用字符流实现纯文本文件的复制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void main(String[] args) throws IOException { File file = new File("C:\\Users\\root\\Desktop\\test\\11.txt"); FileReader fr = new FileReader(file); FileWriter fw = new FileWriter("C:\\Users\\root\\Desktop\\test\\22.txt");
char[] chars = new char[3]; int len; while((len=fr.read(chars))!=-1){ fw.write(chars,0,len); }
fw.close(); fr.close(); }
|
IO流-4
1. 高效缓冲流
1.1 概述
对硬盘进行数据的读取相比于从内存中存取数据要慢的多。所以JDK为我们提供了高效缓冲流来提高我们IO流的效率。内部原理就是借助内存的缓冲区来减少硬盘IO的次数,提高性能。
1.2 分类
字节流
输入流
BufferedInputStream
输出流
BufferedOutputStream
字符流
输入流
BufferedReader
输出流
BufferedWriter
1.2 对象的创建
构造方法:
1 2 3 4
| public BufferedInputStream(InputStream in) public BufferedOutputStream(OutputStream out) public BufferedReader(Reader in) public BufferedWriter(Writer out)
|
范例:
1 2 3 4 5 6 7 8 9
| public static void main(String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\root\\Desktop\\test\\汉字.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\root\\Desktop\\test\\汉字3.txt"));
BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\root\\Desktop\\test\\汉字3.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\root\\Desktop\\test\\汉字3.txt")); }
|
1.3 特有的方法
类 |
方法 |
作用 |
BufferedReader |
public String readLine() throws IOException |
一次读取一行数据,读到的内容不包含换行符,读到了文件末尾返回null。 |
BufferedWriter |
public void newLine() throws IOException |
写入一个换行符,会根据系统变化 |
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\root\\Desktop\\test\\333.txt"));
String line; while((line=br.readLine())!=null){ System.out.println(line); } br.close();
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static void main(String[] args) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\root\\Desktop\\test\\444.txt"));
bw.write("你好啊"); bw.newLine(); bw.write("我很好"); bw.close(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("C:\\Users\\root\\Desktop\\test\\333.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\root\\Desktop\\test\\444.txt"));
String line; while((line=br.readLine())!=null){ bw.write(line); bw.newLine(); }
br.close(); bw.close(); }
|
1.4 应用场景
如果想让IO操作效率更高或者想使用特有的方法(readLine、newLine)就可以使用高效缓冲流。
2. 转换流
2.1 概述
如果我们需要把字节流转换成字符流,可以使用转换流来实现转换。
2.2 分类
流类型 |
类 |
输入流 |
InputStreamReader |
输出流 |
OutputStreamWriter |
2.2 转换流的使用
当我们需要把字节流转换成字符流时直接使用转换流的构造方法进行转换即可。
1 2 3 4
| public InputStreamReader(InputStream in) public InputStreamReader(InputStream in, String charsetName) public OutputStreamWriter(OutputStream out) public OutputStreamWriter(OutputStream out, String charsetName)
|
范例:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws FileNotFoundException { FileInputStream fis = new FileInputStream("C:\\Users\\root\\Desktop\\test\\汉字.txt"); FileOutputStream fos = new FileOutputStream("C:\\Users\\root\\Desktop\\test\\转换流测试.txt");
InputStreamReader isr = new InputStreamReader(fis); OutputStreamWriter osw = new OutputStreamWriter(fos); }
|
3. Properties
Properties 其实是一个Map集合,其Key和Value都是String类型。他提供了和流结合的方法,可以方便我们把集合中的数据写入文件或者是把文件中的数据读取到集合中。
3.1 对象创建
构造方法:
范例:
1 2 3
| public static void main(String[] args) { Properties properties = new Properties(); }
|
3.2 常用方法
Map集合的方法Properties都有,这里不做演示。因为我们在使用Properties的时候一般都是使用其特有的一些方法。
常用方法:
1 2 3
| public synchronized Object setProperty(String key, String value) public String getProperty(String key) public Set<String> stringPropertyNames()
|
范例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) { Properties properties = new Properties(); properties.setProperty("name","三更"); properties.setProperty("age","17");
String v = properties.getProperty("name");
Set<String> keys = properties.stringPropertyNames(); for (String key : keys) { String value = properties.getProperty(key); System.out.println(key+"===="+value); } }
|
3.2 和流结合的方法
1 2 3 4
| public synchronized void load(Reader reader) throws IOException public synchronized void load(InputStream inStream) throws IOException public void store(Writer writer, String comments) throws IOException public void store(OutputStream out, String comments) throws IOException
|
范例:
1 2 3 4 5 6 7 8 9 10
| public static void main(String[] args) throws IOException { Properties pro = new Properties(); pro.setProperty("name","三更"); pro.setProperty("age","16"); FileWriter fw = new FileWriter("C:\\Users\\root\\Desktop\\test\\proTest.txt"); pro.store(fw,"java"); fw.close(); }
|
1 2 3 4 5 6 7 8
| public static void main(String[] args) throws IOException { Properties pro = new Properties(); FileReader fr = new FileReader("C:\\Users\\root\\Desktop\\test\\proTest.txt"); pro.load(fr);
}
|
3.3 应用场景
Properties主要是用来读取和写入配置文件时使用。要求配置文件中的数据格式是: key=value