IO流
1.File类
-
java.io.File类: 文件和文件目录路径的抽象表示形式,与平台无关
1.java所有的文件操作都在java.io这个包下操作。
2.File表示一个文件或者一个文件目录
-
File能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
-
构造函数:
-
- public File(String pathname) 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
-
-
-
绝对路径: 是一个固定的路径,从盘符开始
-
相对路径: 是相对于某个位置开始
1.String pathname:字符串路径名。
-
-
2.绝对路径:从盘符开始,完整的描述文件位置的路径就是绝对路径。(D:\test\java-demo1\a.txt)
3.相对路径:java中默认的当前路径在user.dir(项目)中存储。(.\java-demo1\a.txt) ```
-
- public File(String parent,String child) 以parent为父路径, child为子路径创建File对象。
- public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象
-
-
路径中的每级目录之间用一个路径分隔符隔开。
-
- windows和DOS系统默认使用“\”来表示
- UNIX和URL使用“/”来表示
-
File类的使用:
-
-
产生文件:
-
1.File file1 = new File("D:\\\file-test\\\a.txt"); 2.File file2 = new File("D:\\\file-test\\\\","a.txt"); 3.File filePath = new File("D:\\file-test\\"); File file3 = new File(filePath,"a.txt"); 4.URI uri=new URI("file:///D:/file-test/a.txt"); file4 = new File(uri); file.createNewFile();
-
-
-
产生文件目录:
-
public boolean mkdir() : 创建文件目录。 如果此文件目录存在, 就不创建。如果此文件目录的上层目录不存在, 也不创建。
-
//只能产生文件的当前目录 file4.mkdir(); //判断文件目录是否存在 if (!filePath.exists()){//如果不存在 filePath.mkdir();//产生当前目录 }
-
- public boolean mkdirs() : 创建文件目录。 如果上层文件目录不存在, 一并创建.
-
//产生所有的子目录 file4.mkdirs();
-
-
删除文件:
-
-
-
public boolean delete(): 删除文件或者文件夹。
-
-
-
- 删除注意事项:Java中的删除不走回收站。要删除一个文件目录, 请注意该文件目录内不能包含文件或者文件目录
-
-
-
file4.delete();
-
-
- 打印文件目录:
-
//打印用户默认目录 System.out.println(System.getPropertie(user.dir)); //打印所有System参数的文件目录 System.out.println(System.getProperties()); //打印项目的运行目录 System.out.println(FileDemo1.class.getResource("/").getPath());//一般文件和配置文件都放在class.path中
File类的获取功能
-
- public String getAbsolutePath(): 获取绝对路径
- public String getPath() : 获取路径
- public String getName() : 获取名称
- public String getParent(): 获取上层文件目录路径。 若无, 返回null
- public long length() : 获取文件长度(即:字节数) 。 不能获取目录的长度。
- public long lastModified() : 获取最后一次的修改时间, 毫秒值
- public String[] list() : 获取指定目录下的所有文件或者文件目录的名称数组
- public File[] listFiles() : 获取指定目录下的所有文件或者文件目录的File数组
-
//获取文件的绝对路径 file4.getAbsolutePath(); //获取文件的路径 file4.getPath(); //获取文件的名称 file4.getName(); //获取文件长度 file4.length(); //获取指定目录下的所有文件或者文件目录的名称数组 String[] files = filePath.list(); for (String s : files) { System.out.println(s); }
public class FileDemo1 {
/**
* File:表示文件或者目录
* @param args
*/
public static void main(String[] args) throws IOException {
File file1 = new File("D:\\file-test\\a.txt");
System.out.println(File.separator);
File file2 = new File("D:\\file-test\\","a.txt");
File filePath = new File("D:\\file-test\\");
File file3 = new File(filePath,"a.txt");
//产生目录
//file4.mkdir();//产生当前目录
if (!filePath.exists()){
filePath.mkdir();//产生当前目录
}
file4.createNewFile();
//默认的文件目录
System.out.println(System.getProperties());
File file5 = new File("a.txt");//user.dir,一般只在测试使用
file5.createNewFile();
//删除文件
//file5.delete();
//获取绝对路径
System.out.println(file5.getAbsolutePath());
//获取文件的路径
System.out.println(file5.getPath());
//获取文件的名称
System.out.println(file5.getName());
//获取文件长度
System.out.println(file5.length());
System.out.println("------------");
String[] files = filePath.list();
//获取指定目录下的所有文件或者文件目录的名称数组
for (String s : files) {
System.out.println(s);
}
}
}
2.IO流原理及流的分类
- Java IO原理
-
I/O是Input/Output的缩写, I/O技术是非常实用的技术, 用于处理设备之间的数据传输。 如读/写文件,网络通讯等。
-
BIO(阻塞IO),NIO,AIO
-
Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。
-
java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
-
输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
-
输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HDpdBHu8-1692186060400)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230813153639032.png)]
- IO流的分类
- 按操作数据单位不同分为: 字节流(8 bit),字符流
- 按数据流的流向不同分为: 输入流,输出流
字节流 | 字符流 | |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
3.字符流和字节流
1.InputStream & Reader
-
InputStream
-
- int read() 从输入流中读取数据的下一个字节。 返回 0 到 255 范围内的 int 字节值。 如果因为已经到达流末尾而没有可用的字节, 则返回值 -1。
- int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 如果因为已经到达流末尾而没有可用的字节, 则返回值 -1。 否则以整数形式返回实际读取的字节数。
- int read(byte[] b, int off,int len) 将输入流中最多 len 个数据字节读入 byte 数组。 尝试读取 len 个字节, 但读取的字节也可能小于该值。 以整数形式返回实际读取的字节数。 如果因为流位于文件末尾而没有可用的字节, 则返回值 -1。
- public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。
//字节输入流 .close() // 关闭此流并释放与此流相关的所有系统资源 .read() // 从输入流中读取数据的下一个字节 .read(byte[] b) // 从输入流中读取一批字节,并存储到一个字节数组b中
//文件字节输入流 FileInputStream(File file) // 读取源是一个文件 FileInputStream(String name) // 读取源是一个路径
-
Reader
-
- int read() 读取单个字符。 作为整数读取的字符, 范围在 0 到 65535 之间 (0x00-0xffff)(2个字节的Unicode码) , 如果已到达流的末尾, 则返回 -1
- int read(char[] cbuf) 将字符读入数组。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。
- int read(char[] cbuf,int off,int len) 将字符读入数组的某一部分。 存到数组cbuf中, 从off处开始存储, 最多读len个字符。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。
- public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。
//字符输入流 .close() // 关闭此流并释放与此流相关的所有系统资源 .read() // 从输入流中读取一个字符 .read(char[] cbuf) // 从输入流中读取一批字符,并放入字符数组cbuf中
//文件字符输入流 FileReader(File file) // 读取源是一个文件 FileReader(String fileName) // 读取源是一个路径
2.OutputStream & Writer
-
OutputStream
-
- void write(int b) 将指定的字节写入此输出流。 write 的常规协定是:向输出流写入一个字节。 要写入的字节是参数 b 的八个低位。 b 的 24 个高位将被忽略。 即写入0~255范围的。
- void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同。
- void write(byte[] b,int off,int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
- public void flush()throws IOException 刷新此输出流并强制写出所有缓冲的输出字节, 调用此方法指示应将这些字节立即写入它们预期的目标。
- public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。
//字节输出流 .close() // 关闭此流并释放与此流相关的所有系统资源 .flush() // 刷新此流并强制所有缓冲的输出字节被写出 .write(byte[] b) // 将b.length长度的字节数组写入到输出流 .write(byte b[], int off, int len) // 从指定的字节数组b,从off偏移量开始,写入len长度的字节 .write(int b) // 将指定的字节输出
//文件字节输出流 FileOutputStream(File file) // 输出的目的地是一个文件 FileOutputStream(String name) // 输出的目的地是一个路径 FileOutputStream(File file, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件 FileOutputStream(String name, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
-
Writer
-
- void write(int c) 写入单个字符。 要写入的字符包含在给定整数值的 16 个低位中, 16 高位被忽略。 即写入0 到 65535 之间的Unicode码。
- void write(char[] cbuf) 写入字符数组。
- void write(char[] cbuf,int off,int len) 写入字符数组的某一部分。 从off开始, 写入len个字符
- void write(String str) 写入字符串。
- void write(String str,int off,int len) 写入字符串的某一部分。
- void flush() 刷新该流的缓冲, 则立即将它们写入预期目标。
- public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。
//字符输出流 .close() // 刷新并关闭此流 .flush() // 刷新此流并强制所有缓冲的字符被写出 .write(int c) // 写出一个字符 .write(char[] cbuf) // 将指定的 cbuf.length长度的字符数组写到此输出流 .write(char[] b, int off, int len) // 从指定的字符数组b,从off偏移量开始,写入len长度的字节 .write(String str) // 写出一个字符串 .write(String str, int off, int len) // 写入字符串的某一部分
//文件字符输出流 FileWriter(File file) // 输出源是一个文件 FileWriter(String fileName) // 输出源是一个路径 FileWriter(File file, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件 FileWriter(String fileName, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
关闭和刷新的区别
flush :刷新缓冲区,把缓冲区中的数据刷新到文件,流对象可以继续使用。 close :关闭流,释放系统资源。关闭前会刷新缓冲区。把缓冲区中的数据刷新到文件,关闭之后流对象就不能使用了 记得关流,不然会一直占用
public class FileDemo2 {
@Test
public void test1(){
try{//一个字符一个字符的读取
FileReader reader = new FileReader("a.txt");
//读取一个字符
char c = (char) reader.read();
System.out.println(c);
int charInt = -1;//字符
//读取一个字符,如果返回-1表示到达文件末尾
while ((charInt = reader.read()) != -1){
System.out.println((char)charInt);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test2(){
try {//多个字符多个字符的读取
FileReader reader = new FileReader("a.txt");
int length = -1;//读取的长度
char[] buffer = new char[5];//读取5个字符
// length = reader.read(buffer);
// System.out.println(buffer);
while ((length = reader.read(buffer)) != -1){
System.out.println(new String(buffer, 0, length));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class WriteDemo1 {
@Test
public void test1(){
FileWriter out = null;
try{
out = new FileWriter("a.txt");
out.write(97);
out.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
out.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test2(){
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader("a.txt");
out = new FileWriter("a.txt");
int length = -1;
char[] buffer = new char[5];
while ((length = in.read(buffer)) != -1){
out.write(buffer, 0, length);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
}catch (IOException e){
throw new RuntimeException(e);
}
}
}
@Test
public void test3(){
FileReader in =null;
FileWriter out = null;
try {
in = new FileReader("a.jpg" );
out = new FileWriter("a1.jpg");
int length = -1;
char[] buffer = new char[5];
while ((length = in.read(buffer)) != -1){
out.write(buffer, 0, length);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
}catch (IOException e){
throw new RuntimeException(e);
}
}
}
}
4.缓冲流
-
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
-
- BufferedInputStream 和 BufferedOutputStream
- BufferedReader 和 BufferedWriter
//字节缓冲流
BufferedInputStream(InputStream in) //创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
BufferedInputStream(InputStream in int size)// 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
BufferedOutputStream(OutputStream out)//创建一个新的缓冲输出流,以将数据写入指定的底层输出流
BufferedOutputStream(OutputStream out, int size)//创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
//字符缓冲流
//构造方法
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
//特有方法
BufferedReader:public String readLine(); //读一行文字。
BufferedWriter:public void newLine(); //写一行行分隔符,由系统属性定义符号。
-
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
-
非缓冲流
- 缓冲流
public class BufferCopy {
/**
* 使用非缓冲流拷贝
* @param from
* @param to
*/
public static void copyNoBuffer(String from, String to) {//把一个文件从文件夹中拷贝到另一个文件夹中
FileInputStream in = null;
FileOutputStream out = null;
try {
//1k、1k的传输
in = new FileInputStream(from);
out = new FileOutputStream(to);
int length = -1;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
// out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
out.close(); //close会自动执行flush
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* 使用缓冲流拷贝
* @param from
* @param to
*/
public static void copyWithBuffer(String from, String to) {
BufferedInputStream in = null;
BufferedOutputStream out = null;
try { //默认值为8k
in = new BufferedInputStream(new FileInputStream(from,) 1024 * 1024);
out = new BufferedOutputStream(new FileOutputStream(to,) 1024 * 1024);
int length = -1;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
}
// out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
out.close(); //close会自动执行flush
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test1() {
Long t1 = System.currentTimeMillis();
// copyNoBuffer("d:\\a.mkv", "d:\\a1.mkv"); 20S
copyWithBuffer("d:\\a.mkv", "d:\\a1.mkv"); 4S
Long t2 = System.currentTimeMillis();
System.out.println((t2 - t1) / 1000 );
}
/**
* 字符缓冲流
* @throws Exception
*/
@Test
public void test2() throws Exception {
BufferedReader in = new BufferedReader(new FileReader("BufferCopy.txt"));
BufferedWriter out = new BufferedWriter(new FileWriter("BufferCopy2.txt"));
String line = null;
//readLine():一行一行的读取
while ((line = in.readLine()) != null) {
out.write(line);
out.newLine();
}
in.close();
out.close();
}
}
5.转换流
-
InputStreamReader
-
- 实现将字节的输入流按指定字符集转换为字符的输入流。
- 需要和InputStream“套接”。
- 构造器
-
-
- public InputStreamReader(InputStream in)
- public InputSreamReader(InputStream in,String charsetName) 如: Reader isr = new InputStreamReader(System.in,”gbk”);
-
-
OutputStreamWriter
-
- 实现将字符的输出流按指定字符集转换为字节的输出流。
- 需要和OutputStream“套接”。
- 构造器
-
-
- public OutputStreamWriter(OutputStream out)
- public OutputSreamWriter(OutputStream out,String charsetName)
-
转换流分类
InputStreamReader:将一个字节的输入流转换为字符的输入流
//构造方法
public inputStreamReader(inputStream in);//创建一个使用默认的字符集的字符流
public inputStreamReader(inputStream in,String charsetName);//创建一个指定字符集的字符流
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
public OutputStreamWriter(OutputStream out);//创建一个使用平台默认的字符集的字符流
public OutputStreamWriter(OutputStream out,String charsetName);//创建一个指定的字符集的字符流
@Test
public void test1() throws Exception {
//默认为UTF-8读取
InputStream in = new FileInputStream("utf8.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
System.out.println(reader.readLine());
//如果是GBK形式,需要指定一下字符集
InputStream in = new FileInputStream("gbk.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "gbk"));
System.out.println(reader.readLine());
}