引言
这个部分整理了io流的相关知识点,有关file类,和I/O流的分类
File
File:文件和目录(文件夹)路径名的抽象表示形式。
File的构造方法:
File(String pathname):把一个路径名称封装成File对象
File(String parent, String child):把一个父路径和一个子路径封装成一个File对象
File(File parent, String child):把一个父路径File对象和一个子路径封装成一个File对象
创建功能:
A:创建文件
public boolean createNewFile():如果文件不存在,就创建。否则,不创建。
需求:D盘下造一个文件a.txt
B:创建目录
public boolean mkdir():如果目录不存在,就创建。否则,不创建。
需求:D盘下造一个文件夹test
public boolean mkdirs():如果目录不存在,就创建。否则,不创建。
即时父目录不存在,也可以连父目录一起创建。
需求:D盘下造一个文件夹(D:/aaa/bbb/ccc)
需求:D盘下造一个文件夹(“D:\ddd\eee\f.txt”);
注意事项:
A:你要造什么东西,就应该用对应的方法。
删除功能:
public boolean delete():既可以删除文件,又可以删除目录。
路径问题:
A:绝对路径 就是以盘符开始的路径(d:\test\aaa\b.txt)
B:相对路径 就是不以盘符开始的路径(a.txt)
一般都是相对应当前的项目而言的。
注意事项:
A:Java程序的删除不走回收站。
B:如果目录内还有内容就不能删除。
判断功能:
public boolean isDirectory():是否是目录
public boolean isFile():是否是文件
public boolean exists():是否存在
public boolean canRead():是否可读
public boolean canWrite():是否可写
public boolean isHidden():是否隐藏
获取功能:
public String getAbsolutePath():获取绝对路径
public String getPath():获取相对路径
public String getName():获取名称
用简单的代码介绍一下相关功能:
package com.stu_01;
import java.io.File;
import java.io.IOException;
public class FileStu01 {
public static void main(String[] args) throws IOException {
//A:创建文件
File file = new File("a.txt");
//System.out.println(file.createNewFile());//true
/* 判断功能
public boolean isDirectory():是否是目录
public boolean isFile():是否是文件
public boolean exists():是否存在
public boolean canRead():是否可读
public boolean canWrite():是否可写
public boolean isHidden():是否隐藏*/
/* System.out.println(file.isDirectory());//false
System.out.println(file.isFile());//true
System.out.println(file.exists());//true
System.out.println(file.canRead());//true
System.out.println(file.canWrite());//true
System.out.println(file.isHidden());//false
*/ /*public String getAbsolutePath():获取绝对路径
public String getPath():获取相对路径
public String getName():获取名称
*/
System.out.println(file.getAbsolutePath());//C:\Users\doumingyue\workspace\第十二天作业_File\a.txt
System.out.println(file.getPath());//a.txt
System.out.println(file.getName());//a.txt
}
}
相应的运行结果在代码中注释
字节流及字节高效流
IO流分类:
流向: 输入流 输出流
数据类型:
字节流
字节输入流
字节输出流
字符流
字符输入流
字符输出流
注意:一般我们在讨论IO的分类时,默认是按照数据类型分的。
字节流:
字节输入流 InputStream(抽象类)
字节输出流 OutputStream(抽象类)
字符流:
字符输入流 Reader
字符输出流 Writer
做一个需求对上述进行理解:
用字节流往一个文本文件中写一句话:”helloworld”。
//字节输出流
package com.stu.outputstream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
//用字节流往一个文本文件中写一句话:"helloworld"。
public class OutputStreamStu01 {
public static void main(String[] args) throws IOException {
//而OutputStream是抽象类,所以我们应该找其子类
FileOutputStream fos = new FileOutputStream("a.txt");
//调用输出流的写数据的方法给文件中写数据
byte[] byf="helloworld".getBytes();
fos.write(byf);
//关流
fos.close();
}
}
编译运行后我们会在该项目的根目录下找到a.txt文件,里面写入了helloworld。
FileOutputStream写数据的方法
write(byte[] b)
write(int b) :一次写一个字节
write(byte[] b, int off, int len) :一次写一个字节数组的一部分
字节输入流:
具体操作步骤:
字节输入流操作步骤:
A:创建字节输入流对象
FileInputStream fis = new FileInputStream(“a.txt”);
B:调用方法读取数据
一次读取一个字节:read() – 测试读取不到内容的时候的返回值(并且用循环改进)
C:释放资源
fis.close
用一个简单的例子进行理解:
把a.txt的内容复制到c.txt中
package com.stu.inputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//把a.txt的内容复制到c.txt中
public class InputStreamStu01 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("c.txt");
int bye;
while((bye=fis.read())!=-1){
fos.write(bye);
}
//关流
fis.close();
fos.close();
}
}
编译运行之后会发现文件a.txt中的内容被复制到c.txt中去了。
数据源:IODemo.java – 读取数据 – InputStream – FileInputStream – 一次读取一个字节
目的地: Copy.java – 写出数据 – OutputStream – FileOutputStream – 一次写一个字节
字节缓冲区流(也叫高效流):
BufferedInputStream(read() 一次读取一个字节, public int read(byte[] b):返回实际读取长度,数据被读取到数组中。)
BufferedOutputStream(write(byte[] b))
流
低级流: 基本的流,可以直接操作文件。
高级流:是操作基本流的流。
String中的编码和解码问题
编码: 把我们能够看懂的字符转换为看不懂的数据
解码:把我们看不懂的数据转换为看得懂的字符
用一个简单的小例子做一说明:
package com.stu.stu;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
//编码:
// 把我们能够看懂的字符转换为看不懂的数据
public class EncodingStu {
public static void main(String[] args) throws IOException {
/*
* public byte[] getBytes(String charsetName)
* 按照给定的编码方式,编码字节数组(gbk,utf-8)
String(byte[] bytes, String charsetName)
按照给定的编码方式解码字符数组
String s = "中国好";
byte[] bytes = s.getBytes("utf-8");
System.out.println(Arrays.toString(bytes));
//String(byte[] bytes, String charsetName)
System.out.println(new String(bytes,"gbk"));
*/
String s="中国好";
byte[] bytes=s.getBytes("utf-8");
System.out.println(Arrays.toString(bytes));//[-28, -72, -83, -27, -101, -67, -27, -91, -67]
byte[] bytes1=s.getBytes("gbk"); System.out.println(Arrays.toString(bytes1));//[-42, -48, -71, -6, -70, -61]
//解码
System.out.println(new String(bytes));//涓浗濂?
System.out.println(new String(bytes1));//中国好
}
}
编译运行结果在代码后的注释可以看到
字符流
Reader
Writer
IO流中的编码和解码问题
OutputStreamWriter:把字节输出流转换为字符输出流
InputStreamReader:把字节输入流转换为字符输入流
package com.stu.outputstreamwriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class OutputStreamWriterStu01 {
public static void main(String[] args) throws IOException {
//写入数据,把字节输出流转换为字符输出流(不指定码表)
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));
osw.write("helloworld");
osw.flush();
osw.close();
//把字节输出流转换为字符输出流(指定码表)
OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("b.txt"),"gbk");
osw2.write("helloworld");
osw2.flush();
osw2.close();
//读取数据, 把字节输入流转换为字符输入流(不指定码表)
//InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
int ch;
while((ch=isr.read())!=-1){
System.out.print((char)ch);//helloworld
}
System.out.println();
//把字节输入流转换为字符输入流(指定码表)
//InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "GBK");
InputStreamReader isr2 = new InputStreamReader(new FileInputStream("b.txt"),"utf-8");
int ch2;
while((ch2=isr2.read())!=-1){
System.out.print((char)ch2);//helloworld
}
}
}
相关运行结果在代码注释部分显示
总结:我们一般创建字符输入或者输出流一般情况下使用系统默认的码表就可以,如果来来回回需要指定码表的话,就显得非常的麻烦了
(将以上创建方式继续简化)
如果采用刚才的方式,创建对象写起来比较复杂。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(“b.txt”));
为了简化这种操作,java就针对这两个转换的字符流提供其子类。
FileReader
FileWriter
它们的默认编码是采用系统编码。
构造学习:
FileWriter(File file)
FileWriter(String fileName)
FileReader(File file)
FileReader(String fileName)
flush()和close()的区别?
A:flush 刷新缓冲区,流对象可以继续
B:close 先刷新缓冲区,再关闭流对象。流对象不可以继续使用了。
在这里,仅对字符输出流的相关功能做一简单代码演示,字符输入流可以仿照字符输出流来理解。
package com.stu.filewriter;
import java.io.FileWriter;
import java.io.IOException;
/*
* 给字符输出流里面利用方法写数据
* 字符输出流操作步骤:
* A:创建字符输出流对象
* B:调用写数据方法
* C:释放资源
* 写数据方法:
* 一次写一个字符 write(int c)
* 一次写一个字符数组write(char[] cbuf)
* 一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
* 一次写一个字符串write(String str)
* 一次写一个字符串的一部分write(String str,int off,int len)
*/
public class FileWriterStu01 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("c.txt");
//一次写一个字符 write(int c)
// fw.write(103);
// //一次写一个字符数组write(char[] cbuf)
// char[] ch={102,99,98,106};
// fw.write(ch);
//一次写一个字符数组的一部分write(char[] cbuf, int off,int len)
// fw.write(ch, 0, 3);
// //一次写一个字符串write(String str)
// fw.write("hello");
//一次写一个字符串的一部分write(String str,int off,int len)
String str="helloworld";
fw.write(str, 1, 5);
fw.close();
}
}
注意:字符流输入输出流复制的文件是有要求的,简单来说只要是记事本打开文件的内容你能够看得懂,就可以用字符流来进行复制,否则不行。
具体原因:像复制MP3或者一些视频文件的时候,如果他的字节个数不是偶数的话,就会造成文件的缺损,因为一个字符等于两个字节。
做一个简单的需求:利用字符流复制java文件(两种方式,一次读写一个字符,一次读写一个字符数组)
package com.stu.copy;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 利用字符流复制java文件(两种方式,一次读写一个字符,一次读写一个字符数组)
*/
public class CopyStu01 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("InputStreamReaderStu.java");
FileWriter fw = new FileWriter("a.java");
//一次读写一个字符
int ch;
while((ch=fr.read())!=-1){
fw.write(ch);
fw.flush();
}
// //一次读写一个字符数组
// char[] chs=new char[1024];
// int len;
// while((len=fr.read(chs))!=-1){
// fw.write(chs, 0, len);
// fw.flush();
// }
//关流
fr.close();
fw.close();
}
}
高效流:
BufferedReader:字符缓冲输入流
构造:BufferedReader(Reader in)
特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
有关高效字符流部分做了相关的代码实现:
package com.stu.bufferedwriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:
* 需求:
* 给文件中写入十个"helloworld",每写一个换一行,每写一行必须写入一个换行符“/r/n”
这样写的弊端,windows系统下的换行符是“/r/n”,Linux是"\n",Mac是"\r",这样会造成代码的通用性不强
* BufferedReader:字符缓冲输入流
构造:BufferedReader(Reader in)
特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
* BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
*/
public class BufferedWriterStu02 {
public static void main(String[] args) throws IOException {
//给文件中写入十个"helloworld",每写一个换一行,每写一行必须写入一个换行符“/r/n”
// FileWriter bw = new FileWriter("e.txt");
String s="helloworld";
// for (int i = 0; i < 10; i++) {
// bw.write(s+"\r\n");
// bw.flush();
// }
/*
* BufferedWriter:字符缓冲输出流
构造:BufferedWriter(Writer out)
特殊方法:public void newLine():会根据系统来确定写入不同的换行符
*/
// BufferedWriter bfw = new BufferedWriter(new FileWriter("f.txt"));
// for (int i = 0; i <10; i++) {
// bfw.write(s);
// bfw.newLine();
// bfw.flush();
// }
/*
BufferedReader:字符缓冲输入流
构造:BufferedReader(Reader in)
特殊方法:public String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
*/
BufferedReader bfr = new BufferedReader(new FileReader("f.txt"));
String line;
while((line=bfr.readLine())!=null){
System.out.println(line);
}
bfr.close();
// bw.close();
// bfw.close();
}
}