Java进阶IO流
IO流
- IO流的分类:
- 按照流的方向,IO流分为:
- 输入流
- 输出流
- 按照流的内容,IO流分为:
- 字节流:适合操作所有文件,音频,视频,图片,文本文件的复制转移等。
- 字符流:只适合操作纯文本文件,读写txt,Java文件等
- 按照流的方向,IO流分为:
- 以下都属于抽象类:
- 字节输入流InputStream
- 字节输出流OutputStream
- 字符输入流Reader
- 字符输出流Writer
文件字节输入流
public class IOTest {
public static void main(String[] args) throws Exception {
//1.创建文件字节输入流管道与源文件接通
InputStream is = new FileInputStream("D:/aaa/qq.txt");
//2.开始读取文件中的字节并输出,每次读取一个字节
//定义一个变量记住每次读取的一个字节
int b;
while ((b = is.read()) != -1) {
System.out.print((char) b);//打印读到的字节并且转换为char字符
}
//每次读取一个字节会导致性能较差,并且读取汉字输出一定会乱码。
//3.开始读取文件中的字节并输出,每次读取多个字节
//定义一个字节数组记住每次读取的字节
byte[]bytes=new byte[1024];
int len;//定义一个变量记住每次读取多少个字节
while((len=is.read(bytes))!=-1){
//把读取到的字节数组转换成字符串输出
String str=new String(bytes,0,len);//代表从第一个字节开始读多少个字节,否则会出现不符合预期的字符。
System.out.println(str);
}
//依然无法避免读取汉字出现乱码的问题,存在截断汉字字节的可能性。
//除非定义一个与文件一样大的字节数组,一次性读取完文件的全部字节。(只适用于读取一个小文件)
//一次性读完文件的全部字节,可以避免读取汉字被截断的缺陷,但只适用于读取一个小文件
byte[] bytes =is.readAllBytes();
String str=new String(bytes);
System.out.println(str);
is.close();
}
}
文件字节输出流
public class IOTest {
public static void main(String[] args) throws Exception {
//1.创建文件字节输出流管道与目标文件接通
// OutputStream os = new FileOutputStream("D:/aaa/ww/txt");//覆盖管道,每次执行会将原来的数据清空
OutputStream os = new FileOutputStream("D:/aaa/ww/txt",true);//每次执行是在原文件内容下追加内容
//2.写入数据
os.write(97);//写入一个字节数据
os.write('b');//写入一个字符数据
os.write('白');//写入一个字符数据,出现乱码,因为write一次写一个字节
os.write("\r\n".getBytes());//在文件中进行换行,\r\n表示回车并换行
//3.写一个字节数组出去
byte[] bytes="中文汉字33ad".getBytes();//将字符串转成字符数组存储起来
os.write(bytes);
//4.写一个字节数组的一部分出去
os.write(bytes,0,3);//从第一个字节开始 写三个字节 出去
os.close();//关闭管道,释放资源
}
}
-
进行文件复制操作
public class IOTest { public static void main(String[] args) throws Exception { //将文件夹aaa下的文件a.txt复制到bbb下并且取名为b.txt InputStream is=new FileInputStream("D;/aaa/a.txt");//要从文件中读取字节,进行管道连接 OutputStream os=new FileOutputStream("D;/bbb/b.txt");//要写入字节到文件,进行管道连接 byte[] bytes=new byte[1024];//一次读数组大小的字节 int len;//记录真实读取到的长度 while((len=is.read(bytes))!=-1){ os.write(bytes,0,len);//将读取到的字节写入新文件中 } System.out.println("复制成功"); is.close(); os.close(); } } -
捕获异常,对上面代码进行优化
public class IOTest { public static void main(String[] args) throws Exception { //将文件夹aaa下的文件a.txt复制到bbb下并且取名为b.txt try (//这里放置资源对象,用完之后,最终会自动调用其close方法关闭 InputStream is=new FileInputStream("D;/aaa/a.txt");//要从文件中读取字节,进行管道连接 OutputStream os=new FileOutputStream("D;/bbb/b.txt");//要写入字节到文件,进行管道连接 ){ byte[] bytes=new byte[1024];//一次读数组大小的字节 int len;//记录真实读取到的长度 while((len=is.read(bytes))!=-1){ os.write(bytes,0,len);//将读取到的字节写入新文件中 } System.out.println("复制成功"); } catch (IOException e) { throw new RuntimeException(e); } } }
文件字符输入流和文件字符输出流与上面的同理
- xx.flush();//刷新缓冲区,将缓冲区中的数据全部写出去,否则数据不会同步到文件中,会随内存消失。
- xx.close();//包含刷新功能。
高级流
- 缓冲流
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWriter
- 对上面的复制功能代码进行改造:
public class IOTest {
public static void main(String[] args) throws Exception {
//将文件夹aaa下的文件a.txt复制到bbb下并且取名为b.txt
try (//这里放置资源对象,用完之后,最终会自动调用其close方法关闭
InputStream is=new FileInputStream("D;/aaa/a.txt");//要从文件中读取字节,进行管道连接
//把低级的字节输入流包装成高级的缓冲字节输入流
InputStream bis=new BufferedInputStream(is);
OutputStream os=new FileOutputStream("D;/bbb/b.txt");//要写入字节到文件,进行管道连接
//把低级的字节输出流包装成高级的缓冲字节输出流
OutputStream cis=new BufferedOutputStream(os);
){
byte[] bytes=new byte[1024];//一次读数组大小的字节
int len;//记录真实读取到的长度
while((len=bis.read(bytes))!=-1){
cis.write(bytes,0,len);//将读取到的字节写入新文件中
}
System.out.println("复制成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- 缓冲字符输入流
public class Test3 {
public static void main(String[] args) {
try( //创建文件字符输入流与源文件接通
Reader fr =new FileReader("D:/aaa/a.txt");
//创建缓冲字符输入流包装低级的字符输入流
BufferedReader br =new BufferedReader(fr);
){
// char[] chs = new char[1024];
// int len;
// while((len=br.read(chs))!=-1){
// String s = new String(chs,0,len);
// System.out.println(s);
// }
System.out.println(br.readLine());//读出一行
//使用循环改进,来按照行读取数据
//定义一个字符串变量用于记住每一次读取的一行数据
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
-
缓冲字符输出流
- 新增一个包装了的换行功能
- xx.newLine();
-
字符输入转换流:InputStreamReader
- 解决不同编码时,字符流读取文本内容乱码问题
- 先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
public class Test3 {
public static void main(String[] args) {
try( //先提取文件的原始字节流
InputStream is=new FileInputStream("D://aaa/a.txt");
//指定字符集,把原始字节流转换成字符输入流
InputStreamReader isr=new InputStreamReader(is,"GBK");//GBK为文件本身的字符集,但我的字符集为UTF-8
//创建缓冲字符输入流包装低级的字符输入流
BufferedReader br=new BufferedReader(isr);
){
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
- 打印流:printStream(字节输出流),printWriter(字符输出流)
- 打印到文件中,实现打印啥出去就是啥。(打印97,就是97而不是a)
public class Test3 {
public static void main(String[] args) {
try (
// PrintStream ps = new PrintStream("D:\\test3.txt");//字节输出流打印,但不支持追加内容,只有低级输出流才有追加数据的功能
PrintStream ps = new PrintStream(new FileOutputStream("D:\\test3.txt",true));//字节输出流打印,这样就支持追加内容
PrintWriter pw = new PrintWriter("D:\\test3.txt");//字符输出流打印
) {
ps.println('a');
pw.println('胡');
} catch (Exception e) {
e.printStackTrace();
}
}
}
-
特殊数据流:
-
特殊数据字节输入流:DataInputStream
DataInputStream dis = new DataInputStream(new FileInputStream("D:/aaa/a.txt")); System.out.println(dis.readInt()); System.out.println(dis.readUTF()); //读写类型要相互对应,观察输出流内容 -
特殊数据字节输出流:DataOutputStream
- 允许把数据和类型一并写出去(看起来像是乱码,但是其实并不是,适用于通信)
DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:/aaa/a.txt")); dos.writeInt(23); dos.writeUTF("哈喽");
-
IO框架
- 需要下载IO资源库
public class IO {
public static void main(String[] args) throws Exception{
//拷贝文件
FileUtils.copyFile(new File("D:/a.txt"),new File("D:/b.txt"));
//拷贝文件夹
FileUtils.copyDirectory(new File("D:/aaa"),new File("D:.bbb"));
}
}
浙公网安备 33010602011771号