本篇文章给大家谈谈java---IO流,以及javaio流分为几种的知识点,同时本文还将给你拓展Java&IO流、JavaIO流、javaIO流(二)IO流概述、Java|IO流等相关知识,希望对各位
本篇文章给大家谈谈java---IO流,以及javaio流分为几种的知识点,同时本文还将给你拓展Java & IO流、Java IO流、java IO流 (二) IO流概述、Java | IO流等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:java---IO流(javaio流分为几种)
一.Java中流的概念细分
1.按流的方向分(容易混淆)
输入流: 数据流向是数据源到程序,以InputStream,Reader结尾的流
输出流: 数据流向是程序到目的地,以OutputStream,Writer结尾的流
2.按处理的数据单元分类
字节流:通常以Stream结尾,以字节为单位获取数据
字符流:通常以Reader/Writer结尾,以字符为单位获取数据
3.按处理对象不同分类
节点流:直接进行文件的读写,系统输入输出(System.in与System.out)都为字节流。
包装流:通过对其他的流进行处理来提高性能
二.Java中的IO流体系
三.常用的流详解
1.文件字节流
FileOutputStream和FileInputStream用来读取文件,适合于所有类型.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.junit.Test;
/**
* 利用文件流,实现文件的复制
* @author MOTI
*
*/
public class Demo_3 {
@Test
public void demo3() {
copyFile("demo1.txt", "demo3.txt");
}
public static void copyFile(String src,String dec) {
FileInputStream is = null;
FileOutputStream os = null;
//为了提高效率,设置一个缓冲数组,读取的文件会暂时放在缓冲数组中
byte[] bytes = new byte[1024];
int len = 0;//每次读取的真实长度,等于-1代表读取完成
try {
is = new FileInputStream(src);
os = new FileOutputStream(dec);
try {
//边读边写
while((len = is.read(bytes)) != -1) {
//将缓冲区的数据写入到文件,注意这里写入的是真实长度,如果使用os.write(bytes)方法,那么写入的就是整个缓冲区的长度为1024
os.write(bytes, 0, len);
}
System.out.println("文件复制成功!");
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
注意:
1.为了减少对硬盘的读写次数,提高效率,通常设置缓存数组.相应的读取时使用read(byte[] b),写入的时候使用write(byte[] b,int off, int length)
2.程序中如果出现多个流,每个流都需要单独关闭,并且关闭顺序要与创建流的顺序相反
2.文件字符流
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import org.junit.Test;
/**
* 使用FileReader和FileWriter进行文本的复制
* @author MOTI
*/
public class Demo_4 {
@Test
public void demo4(){
copyFile("demo1.txt", "demo4.txt");
}
public static void copyFile(String src,String dec){
FileReader fr = null;
FileWriter fw = null;
int len = 0;
//为了提高效率,缓冲区用的也是字符数组
char[] chars = new char[1024];
try {
fr = new FileReader(new File(src));
fw = new FileWriter(new File(dec));
while((len = fr.read(chars)) != -1){
fw.write(chars, 0, len);
}
System.out.println("文本复制成功!");
} catch (Exception e) {
e.printStackTrace();
}finally{
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.缓冲字节流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.junit.Test;
/**
* 使用缓冲字节流实现文件的高效复制
* @author MOTI
*
*/
public class Demo_5 {
@Test
public void demo5(){
copyFile("demo1.txt", "demo5.txt");
}
public static void copyFile(String src,String dec){
FileInputStream is = null;
FileOutputStream os = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
int len = 0;
try {
is = new FileInputStream(src);
os = new FileOutputStream(dec);
/*
使用缓冲字节流包装文件字节流,增加缓冲功能,提高效率
缓冲区的大小,默认8192,也可以自定义
*/
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(os);
while((len = bis.read()) != -1){
bos.write(len);
}
System.out.println("文件复制成功!");
} catch (Exception e) {
e.printStackTrace();
}finally{
if(bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(os != null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
注意:关流的顺序"后开启的先关闭"
4.缓冲字符流
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import org.junit.Test;
/**
* 使用缓冲字符流,实现文本的复制
* @author MOTI
* BufferedReader类提供了更为方便的readline(),直接按行读取
*/
public class Demo_6 {
@Test
public void demo6(){
copyFile("demo1.txt", "demo6.txt");
}
public static void copyFile(String src, String dec){
FileReader fr = null;
FileWriter fw = null;
BufferedReader br = null;
BufferedWriter bw = null;
String tempString = "";
try {
fr = new FileReader(src);
fw = new FileWriter(dec);
/*
使用缓冲字符流包装
*/
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
while((tempString = br.readLine()) != null){
//将读到的一行字符串写入文件
bw.write(tempString);
//下一次写入之前先换行,不然就在第一行一直追加
bw.newLine();
}
System.out.println("文本复制成功!");
} catch (Exception e) {
e.printStackTrace();
}finally{
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
注意:
1.readline()方法是BufferedReader特有的方法
2.写入一行后要记得使用newLine()方法换行
5.数据流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.junit.Test;
/**
*
* @author MOTI
* DataInputStream
* DataOutputStream
*/
public class Demo_8 {
@Test
public void demo8(){
DataInputStream dis = null;
DataOutputStream dos = null;
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("demo8.txt");
fis = new FileInputStream("demo8.txt");
//使用数据流对缓冲流进行包装,增加缓冲功能
dis = new DataInputStream(new BufferedInputStream(fis));
dos = new DataOutputStream(new BufferedOutputStream(fos));
//将下列数据写入到文件
dos.writeInt(520);
dos.writeUTF("哈哈哈哈,我是莫提!");
dos.writeChar(''H'');
//手动刷新缓冲区
dos.flush();
//直接读取数据,读取的顺序要与写入的顺序一致,不然会读取到错误数据
System.out.println(dis.readInt());
System.out.println(dis.readUTF());
System.out.println(dis.readChar());
} catch (Exception e) {
e.printStackTrace();
}finally{
if(dos != null){
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(dis != null){
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
注意:使用数据流时,读取顺序一定要与写入顺序一致,否则不能正确的读取数据.
6.对象流
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Date;
import org.junit.Test;
/**
* 对象流:数据源是一个对象,要求该对象的必须要进行序列化和反序列化操作
* 对象流对象也可以对基本数据类型进行读写操作
* @author MOTI
*
*/
public class Dmeo_10 {
@Test
public void demo10() {
write();
read();
}
/**
* 使用对象输出流将数据写入文件
*/
public static void write() {
//创建一个文件输出流,并包装缓冲流,增加缓冲功能
OutputStream os = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
try {
os = new FileOutputStream(new File("demo10.txt"));
bos = new BufferedOutputStream(os);
oos = new ObjectOutputStream(bos);
//使用Object输出流
oos.writeInt(520);
oos.writeDouble(2.50);
oos.writeUTF("我是莫提!");
//对象流对象可以对对象类型进行读写操作,但是要求必须实现序列化的接口(这里以Date对象为例)
oos.writeObject(new Date());
System.out.println("写入成功!");
} catch (Exception e) {
e.printStackTrace();
}finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(os != null) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 使用对象输入流将数据读入程序
*/
public static void read() {
//创建一个文件输入流,并包装缓冲流,增加缓冲功能
InputStream is = null;
BufferedInputStream bis = null;
ObjectInputStream ois = null;
try {
is = new FileInputStream(new File("demo10.txt"));
bis = new BufferedInputStream(is);
ois = new ObjectInputStream(bis);
//使用Object输入流按照顺序读取
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
System.out.println(ois.readObject().toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
if(ois != null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(bis != null) {
try {
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(is != null) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
注意:
1.对象流不尽可以读写对象,还可以读写基本数据类型
2.使用对象流时,该对象必须经过序列化和反序列化
3.系统提供的类(如:Date)已经实现了序列化接口,自定义类必须手动实现
7.转换流
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import org.junit.Test;
/**
* 转换流:将字节流转换为字符流
* @author MOTI
*
*/
public class Demo_9 {
public static void main(String[] args) {
//创建字符输入和输出流:使用转换流将字节流转换为字符流
BufferedReader br = null;
BufferedWriter bw = null;
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
try {
String str = br.readLine();
while(!"exit".equals(str)){
bw.write(str);
bw.newLine();
bw.flush();
str = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
8.随意访问文件流
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Iterator;
/**
* 随意访问文件流:实现对一个文件的读和写,可以访问文件的任意位置
* @author MOTI
*
*/
public class Demo_11 {
public static void main(String[] args) {
RandomAccessFile raf = null;
int[] data = {10,20,30,40,50,60,70,80,90,100};
try {
raf = new RandomAccessFile("demo11.txt", "rw");
for (int i : data) {
raf.writeInt(i);
}
//直接读取文件,位置从第36个字节开始
raf.seek(4);
System.out.println(raf.readInt());//读取4个字节(int为4个字节)
//直接读取数据,隔一个读取一个
for (int i = 0; i < data.length; i += 2) {
raf.seek(i * 4);
System.out.print(raf.readInt()+"\t");
}
System.out.println();
//在第8字节处,插入新数据,替换原来的30
raf.seek(8);
raf.writeInt(520);
//遍历查看结果
for (int i = 0; i < data.length; i ++) {
raf.seek(i * 4);
System.out.print(raf.readInt()+"\t");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意学习这个流需要掌握三个核心方法:
1.RandomAccessFile(String name, String mode);
name 用于确定文件,mode去r(读),或rw(读写),以此来确定对流的访问权限
2.seek(long a);
用来定位流对象读写文件的位置,a确定读写位置距离文件开头的字节数.
3.getFilePointer();
用来获得流当前的读写位置
四.Java对象的序列化和反序列化
1.序列化和反序列化的概念
把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。
对象的序列化主要有两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。
2.JDK类库中的序列化API
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
对象序列化包括如下步骤:
1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
2) 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
2) 通过对象输入流的readObject()方法读取对象
准备一个Student类,并让该类实现Serializable接口
import java.io.Serializable;
public class Student implements Serializable {
// 添加序列化ID,他决定了是否能够反序列化成功
private static final long serialVersionUID = 1L;
private String name;
private int age;
boolean isMan;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isMan() {
return isMan;
}
public void setMan(boolean isMan) {
this.isMan = isMan;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", isMan=" + isMan + "]";
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age, boolean isMan) {
super();
this.name = name;
this.age = age;
this.isMan = isMan;
}
}
开始将Student类的对象序列化和反序列化
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* java 对象的序列化和反序列化
* @author MOTI
*
*/
public class SerializableTest {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
Student student = new Student("莫提", 20, true);
Student student1 = new Student("Moti", 20, true);
//通过ObjectOutputStream将Student对象写到文件中,即为序列化
try {
fos = new FileOutputStream("serializabletest.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(student);
oos.writeObject(student1);
System.out.println("序列化成功!");
//**************************************************
//通过ObjectInputStream将文件中的数据变回原来的对象
fis = new FileInputStream("serializabletest.txt");
ois = new ObjectInputStream(fis);
Student s = (Student) ois.readObject();
Student s1 = (Student) ois.readObject();
System.out.println(s);
System.out.println(s1);
} catch (Exception e) {
e.printStackTrace();
}finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Java & IO流
Java IO流
1、站在内存的角度看待方向,从其他设备进入内存的,都是输入,从内存到其他设备的,都是输出
I/O就是用于设备之间进行数据交互的对象所属的类型
2、java中操作设备设备之间数据传输的对象,都是IO流对象,这些对象所属的类型,都在io包中
3、按照流向分为输入流和输出流
输入流:其它设备到内存的流对象 进行读取
输出流:内存流到其它设备的流对象 进行写出
4、按照功能分为字节流和字符流
字节流:直接操作字节的流对象
字符流:直接操作字符的流对象 字符流 = 字节流+编码格式
5、字节流:
输入(读取):InputStream 使用子类操作 FileInputStream(File file) FileInputStream(String path)
read()一个个字节读取 read(byte[] b)一个个读取字节到数组,返回数组
输出(写入):OutputStream 使用子类操作 FileOutputStream(File file) FileInputStream(String path)
writer()一个个字节写入 writer(byte[] b)
6、字符流:使用字节流可以操作字符,但字符长度不一致时会产生乱码。注:字符流无法操作非纯文本文件
输入(读取):Reader 使用子类操作 FileReader(File file) FileReader(String path)
方法同字节流,用来处理不是一个字符长度的的字符文件 高效缓冲流多一个readLine()一次读取一行
输出(写入):Writer 使用子类操作 FileWriter(File file) FileWriter(String path)
方法同字节流,但高效缓冲流有特有方法newLine() 用来写换行符,解决各个系统换行符不同问题


import java.io.FileInputStream;
public class test1 {
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("test.txt");
int i=0;
byte[] b = new byte[2];
while((i=fis.read(b))!=-1) {
System.out.println(new String(b,0,i));
}
}
}
7、在使用流操作之前,应进行导包,io包,在操作时应解决异常,操作完毕后应关闭资源
8、高效缓冲流 BufferedInputStream和BufferedOutputStream
1、采用装修设计模式,对某个类的功能进行增强(且不用继承该类,将该类的一个对象传入该类)
2、原理:该类型提供了一个8192字节的数组,当外界调用read()方法时,一次性的读取8192个字节到数组中,对象再次调用时就不需要访问磁盘。写入时也直接写进数组,等8192字节写满后,一次性写入,不需要一直写入磁盘,如果没有写满,在关闭流对象时也会写入磁盘。


public class Test2 {
public static void main(String[] args) {
// 装修设计模式
Man m = new Man();
SuperMan superman = new SuperMan(m);
superman.fly();
}
}
class Man{
public void run() {
System.out.println("i can run");
}
}
class SuperMan{
Man man = null;
public SuperMan(Man man) {
this.man = man;
}
public void run() {
man.run();
System.out.println("i can fly");
}
}
9、close()和flush()
close()方法使用时会先调用flush()方法
流对象一旦使用close()关闭,则无法继续使用
flush()只是将缓冲区的数据刷新到相应的文件,不会关闭流对象,字节流会自动刷新,字符流则需要手动刷新
10、练习


import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class MoniRead {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
MyInputStream m = new MyInputStream("aa.txt");
byte[] b = new byte[2];
int len=0;
while((len=m.myRead(b))!=-1) {
System.out.println(new String(b,0,len));
}
}
}
class MyInputStream{
private File f;
private FileInputStream f1;
public MyInputStream(String s) throws FileNotFoundException {
f = new File(s);
if(!f.exists()) {
FileNotFoundException e = new FileNotFoundException();
throw e;
}
f1 = new FileInputStream(f);
}
public MyInputStream(File f) throws FileNotFoundException {
if(!f.exists()) {
FileNotFoundException e = new FileNotFoundException();
throw e;
}
f1 = new FileInputStream(f);
}
// read(byte[] b) int 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
public int myRead(byte[] b) throws IOException {
int i=0;
int len=0;
while(len<b.length&&(i=f1.read())!=-1) {
b[len]=(byte)i;
len++;
}
return len;
}
// read() 从输入流中读取数据的下一个字节。 int
public int myRead() throws IOException {
return f1.read();
}
}


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class MoniReader {
public static void main(String[] args) throws Exception {
File f = new File("aa.txt");
FileReader fr = new FileReader(f);
MyBufferedReader mbr = new MyBufferedReader(fr);
String line=null;
while((line = mbr.myReadLine())!=null) {
System.out.println(line);
}
}
}
class MyBufferedReader{
private BufferedReader br ;
public MyBufferedReader(FileReader f){
br = new BufferedReader(f);
}
public String myReadLine() throws IOException {
int i=0;
StringBuilder s = new StringBuilder();
while((i=br.read())!=-1&&(char)i!=''\r'') {
if((char)i==''\n'') {continue;}
s.append((char)i);
}
if(s.length()==0) {
return null;
}
return s.toString();
}
}


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Scanner;
/*
* 键盘录入一个文件夹路径,作为源文件夹;键盘录入一个文件夹路径,作为目标文件夹
写代码将源文件夹拷贝到目标文件夹中
*/
public class Test {
public static void main(String[] args) throws Exception {
File src = getFile();//获取源文件
File des = getFile();//获取目标文件
copy(src,des);//进行复制
}
private static void copy(File src, File des) throws Exception {
File newSrc = new File(des,src.getName());//在目标文件中新建与源文件同名的文件夹
newSrc.mkdir();
File[] listFiles = src.listFiles();
if(listFiles!=null) {
for(File subFile:listFiles) {
if(subFile.isDirectory()) {
copy(subFile,newSrc);//如果子文件是文件夹,递归调用本方法
}else {
File desFile = new File(newSrc,subFile.getName());//创建想要复制的文件
FileInputStream fis = new FileInputStream(subFile);//将源文件关联
BufferedInputStream bis = new BufferedInputStream(fis);//封装增强
FileOutputStream fos = new FileOutputStream(desFile);//目标文件关联
BufferedOutputStream bos = new BufferedOutputStream(fos);//封装增强
int b;
while((b=bis.read())!=-1) {
bos.write(b);
}
bos.close();
bis.close();
}
}
}
}
private static File getFile() {
Scanner sc = new Scanner(System.in);
while(true) {
String s = sc.nextLine();
File file = new File(s);
if(file.isDirectory()) {
return file;
}else {
System.out.println("非法录入");
}
}
}
}


import java.io.File;
import java.util.Scanner;
//1、键盘录入一个文件夹路径,删除该文件夹(包含文件夹内容)
public class Test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
File file = new File(s);
deleteFile(file);
}
public static void deleteFile(File file) {
if(file.exists()) {
File[] listFiles = file.listFiles();
if(null==listFiles||listFiles.length==0) {
file.delete();
return;
}
for(File f:listFiles) {
deleteFile(f);
}
file.delete();
}
}
}


import java.io.File;
import java.util.Scanner;
//递归实现输入任意目录,列出文件以及文件夹
public class Test2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
while(true) {
printAll(getFile());
System.out.println("是否继续?继续请输入1,退出请输入0");
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
if(i==1) {
continue;
}else {
break;
}
}
}
public static File getFile() {
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("请输入想要查询的文件路径");
String s = sc.nextLine();
File file = new File(s);
if(file.exists()) {
return file;
}else {
System.out.println("请重新输入");
}
}
}
public static void printAll(File file) {
System.out.println(file.getName());
if(file.isDirectory()) {
File[] listFiles = file.listFiles();
for(File subFile:listFiles) {
printAll(subFile);
}
}
}
}


//对拷贝的效率进行查询,可以测试高效缓冲流的效率
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Scanner;
public class Demo03 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File dsc = getFile();
File src = getFile();
FileInputStream f1 = new FileInputStream(src);
BufferedInputStream bis = new BufferedInputStream(f1);
if(!dsc.exists()) {
dsc.createNewFile();
}
FileOutputStream f2 = new FileOutputStream(dsc);
BufferedOutputStream bos = new BufferedOutputStream(f2);
byte[] b = new byte[1024];
int len=0;
long startTime = System.currentTimeMillis();
while((len=bis.read(b))!=-1) {
bos.write(b);
double d = dsc.length();
System.out.printf("文件已经复制了%.2f%%\n",d*100/src.length());
}
long endTime = System.currentTimeMillis();
System.out.println("总共用时"+(endTime-startTime)/1000.000+"秒");
bos.close();
bis.close();
}
public static File getFile() {
Scanner sc = new Scanner(System.in);
while(true) {
System.out.println("请输入想要查询的文件路径");
String s = sc.nextLine();
File file = new File(s);
if(file.exists()) {
return file;
}else {
System.out.println("请重新输入");
}
}
}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class Test{
public static void main(String[] args) throws IOException {
InputStream is = System.in;
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
Scanner sc = new Scanner(System.in);
}
}


/*
* 键盘录入一个文件路径,将该文件反转
反转:第一行变成最后一行,第二行变成倒数第二行
*/
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.LinkedList;
import java.util.List;
public class Demo04 {
public static void main(String[] args) throws Exception {
File file = new File("aa.txt");
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
File file2 = new File("bb.txt");
FileWriter fw = new FileWriter(file2);
BufferedWriter bw = new BufferedWriter(fw);
LinkedList<String> list = new LinkedList<>();
String str = null;
while((str=br.readLine())!=null) {
list.addFirst(str);
}
while(list.size()>0) {
bw.write(list.removeFirst());
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
java IO流 (二) IO流概述
1.流的分类
* 1.操作数据单位:字节流、字符流
* 2.数据的流向:输入流、输出流
* 3.流的角色:节点流、处理流
图示:
2.流的体系结构
说明:红框对应的是IO流中的4个抽象基类。
蓝框的流需要大家重点关注。
3.重点说明的几个流结构
4.输入、输出的标准化过程
4.1 输入过程
① 创建File类的对象,指明读取的数据的来源。(要求此文件一定要存在)
② 创建相应的输入流,将File类的对象作为参数,传入流的构造器中
③ 具体的读入过程:
创建相应的byte[] 或 char[]。
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。
4.2 输出过程
① 创建File类的对象,指明写出的数据的位置。(不要求此文件一定要存在)
② 创建相应的输出流,将File类的对象作为参数,传入流的构造器中
③ 具体的写出过程:
write(char[]/byte[] buffer,0,len)
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。
Java | IO流
概述
Java程序中,对于数据的输入/输出
操作以“流(stream)”
的方式进行。
流的分类
- 按操作数据单位的不同分为:
字节流(8bit)
,字符流(16 bit)
- 按数据流的流向不同分为:
输入流
,输出流
- 按流的角色不同分为:
节点流
,处理流
关于字节流和字符流的区别:
- 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
- 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
- 字节流:一次读入或读出是8位二进制。
- 字符流:一次读入或读出是16位二进制。
输入流和输出流
- 输入流只能进行读操作
- 输出流只能进行写操作
节点流和处理流
节点流
:直接从数据源或者目的地读写数据
处理流
:不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
Java IO流体系
Java中IO流体系如下表所示,最基本的四个抽象基类分别是:InputStream
、OutputStream
、Reader
、Writer
。表格每一列的类都是继承与第一行的抽象基类的。
常用的字符流
FileReader
通常一个流的使用由以下4个步骤组成:
- 提供File类的对象,指明要操作的文件
- 提供具体的流
- 根据不同流,进行不同的操作
- 流的关闭操作
比如以FileReader流为例,那么它的使用步骤是:
- 实例化File类的对象,指明要操作的文件
- 提供具体的流,FileReader流的实例化
- 进行数据的读入操作
- 流的关闭操作
虽然Java IO流体系有众多的类,但是所有的流都基本按照这几个步骤来使用的。下面记录一下FileReader的使用,数据的读入操作。
@Test
public void testFileReader() throws IOException { // 抛出异常
// 1. 实例化File类对象,指明要操作的文件
File file = new File("Hello.txt");
// 2. 提供具体的流
FileReader fr = new FileReader(file);
// 3. 数据的读入
// read():返回读入的一个字符,如果达到文件末尾,那么返回-1
int data = fr.read();
while(data != -1){
System.out.print((char)data);
data = fr.read();
}
// 4. 流的关闭操作
fr.close();
}
上面例子中,通过File类实例化了一个File对象,然后将其当做参数传入了FileReader类进行实例化,之后调用read()方法进行数据的读入,最后执行流的关闭。
关于上面代码有几个需要注意的点:
-
File file = new File("Hello.txt");
这段代码使用的是相对路径,如果是使用IDEA进行编写的,那么这个相对路径在单元测试方法和main方法中有所区别。在单元测试方法中使用相对路径,那么相对的是模块的路径,而在main方法中相对的是项目的路径。比如,这里模块名Day07,这个模块下有文件Hello.txt,而模块位于项目JavaSenior下,那么File类实例化后的实例文件路径如下代码所示:
public class FileReaderTest {
// 在main方法中,输出:D:\code\Java\JavaSenior\Hello.txt
public static void main(String[] args) {
File file = new File("Hello.txt");
System.out.println(file.getAbsolutePath());
}
// 在单元测试方法中,输出:D:\code\Java\JavaSenior\Day07\Hello.txt
@Test
public void test4(){
File file = new File("Hello.txt");
System.out.println(file.getAbsolutePath());
}
}
- 由于创建流不能被Java垃圾回收机制所处理,所以需要手动进行流的关闭操作,但是由于异常,在步骤1,2,3可能出现异常导致第4步(流的关闭)不能被执行,导致资源不能及时回收,所以为了保证资源一定可以执行关闭操作,需要使用try-catch-finally进行处理,而不建议使用抛出的方式。所以,比较规范的流使用代码应该如下:
@Test
public void test2(){
FileReader fr = null;
try{
File file = new File("Hello.txt");
fr = new FileReader(file);
int data;
while ((data = fr.read()) != -1){
System.out.println((char)data);
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (fr != null){
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
read()
方法:读取单个字符。作为整数读取的字符,范围在0-65535之间(2个字节的Unicode码),如果已到达流的末尾,则返回-1。 -
read(char cbuf[])
:将字符存入数组,并且返回本次读取的字符数,如果到达流的末尾,则返回-1。
@Test
public void test3() {
FileReader fr = null;
try {
// 1. File类的实例化
File file = new File("Hello.txt");
// 2. FileReader流的实例化
fr = new FileReader(file);
// 3. 读入的操作
char[] cbuf = new char[5];
int len;
/*
假如Hello.txt里的文件内容是helloworld123,这里的read(cbuf)指的是读取5个字符,
即第一次读取hello,返回5,第二次读取world,返回5,
第三次读取123,因为只有123了,返回3,第四次返回-1。
所以3次循环,len变量的值为5,5,3,最后一次为-1。
*/
while ((len = fr.read(cbuf)) != -1) {
// 遍历操作错误的写法
// for (int i = 0; i < arr.length; i++) {
// System.out.println(arr[i]);
// }
// 正确的遍历操作一:
// for (int i = 0; i < len; i++) {
// System.out.print(arr[i]);
// }
// 错误的写法二:
// String str = new String(arr);
// System.out.println(str);
// 正确的写法二:
String str = new String(cbuf,0,len);
System.out.print(str);
}
}catch (IOException e){
e.printStackTrace();
}finally {
// 4. 流资源的关闭
try {
if (fr != null) {
fr.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
未完待续...
我们今天的关于java---IO流和javaio流分为几种的分享就到这里,谢谢您的阅读,如果想了解更多关于Java & IO流、Java IO流、java IO流 (二) IO流概述、Java | IO流的相关信息,可以在本站进行搜索。
本文标签: