Java IO


IO类

IO本身就是输入输出的意思,IO类就是为了与磁盘进行IO相关操作的工具、桥梁;

Java IO

IO类基本可以分成字节流字符流
而既然是IO,那不管是哪个流都是分为输入和输出两大块


字节流

字节流

InputStream(抽象)(字节输入流)

InputStream是所有字节输入流的抽象基类,提供字节输入的通用方法

基本方法:

read() //从文件中读取数据的下一字节
read(byte[]) //从文件中读取一个数组量的字节
read(byte[], int, int) //从文件中读取限定位置数量的字节

注:当读取不到字节时会返回 -1


FileInputStream

该流是父类提供用于实例化的读取文件的输入流,能从指定文件中读取字节,从而读取文件内容

构造方法有两个:

  1. 需要实例化一个File文件对象
    • FileInputStream( File )
  2. 不用实例化File对象
    • FileInputStream( String )

使用方式

  1. 一个一个字节读取(效率慢)
public static void main(String[] args) throws IOException {
    //创建一个字节输入流对象,必须明确数据源
    File file = new File("c:\\file.txt");
    FileInputStream fis = new FileInputStream(file);
    
    //使用 read()一次读一个字节。
    int ch = 0;
    while((ch=fis.read())!=-1){
        System.out.println("ch="+(char)ch);		
    }
    fis.close();
}
  1. 一组一组数组读取
public static void main(String[] args) throws IOException {
    // 创建一个字节输入流对象,必须明确数据源
    File file = new File("c:\\file.txt");
    FileInputStream fis = new FileInputStream(file);
    
    // 创建一个字节数组。
    byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。		
    int len = 0;
    while((len=fis.read(buf))!=-1){
        System.out.println(new String(buf,0,len));
    }
    fis.close();
}

BufferedInputStream(字节缓冲输入流)

这是FilterInputStream的子类,它除了父类功能之外还提供了 “缓冲”“mark标记”“重置” 等功能方法

构造方法:

  1. BufferedInputStream( FileInputStream )

使用方法

		FileInputStream fileIn = new FileInputStream("abc.txt");
		//1, 把基本的流包装成高效的流
		BufferedInputStream in = new BufferedInputStream(fileIn);
		//2,读数据
		int ch = -1;
		while ( (ch = in.read()) != -1 ) {
            System.out.print((char)ch);
		}
		in.close();

OutputStream(抽象)(字节输出流)

OutputStream是所有字节输出流的抽象基类,提供内存字节输出到文件的通用方法

基本方法:

write(int) //将指定字节写入输出流
write(byte[]) //将一定数量字节从数组写入输出流
write(byte[], int, int) //将指定数组指定位置数量写入输出流

注:如果文件不存在,则会创建该文件,如果存在,则覆盖


FileOutputStream

该流是父类提供用于实例化的文件数据输出流,能将内存数据写入磁盘文件上

构造方法有四个:

  1. 需要实例化一个File文件对象
    • FileOutputStream( File )
    • FileOutputStream( Fileboolean )
  2. 不用实例化File对象
    • FileOutputStream( String )
    • FileOutputStream( String , boolean )

这里boolean代表如果有同名文件,是否在文件内容末位继续添加写入内容(不覆盖)

使用方式

public static void main(String[] args) throws IOException {
    //创建存储数据的文件。
    File file = new File("c:\\file.txt");
    //创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
    FileOutputStream fos = new FileOutputStream(file ,true);
    String str = "\r\n"+"HelloIO";
    //调用父类中的write方法。
    fos.write(str.getBytes());
    //关闭流资源。
    fos.close();
}

BufferedOutputStream(字节缓冲输出流)

这是FilterInputStream的子类,它除了父类功能之外还提供了 “缓冲” 等功能方法

构造方法:

  1. BufferedOutputStream( FileOutputStream )

使用方法

	//创建基本的字节输出流
	FileOutputStream fileOut = new FileOutputStream("abc.txt");
	//使用高效的流,把基本的流进行封装,实现速度的提升
	BufferedOutputStream out = new BufferedOutputStream(fileOut);
	//2,写数据
	out.write("hello".getBytes());
	//3,关闭流
	out.close();

练习
  1. 使用字节流复制文件
public static void main(String[] args) throws IOException {
    File srcFile = new File("c:\\YesDir\test.JPG");
    File destFile = new File("copyTest.JPG");
    // 明确字节流 输入流和源相关联,输出流和目的关联。
    FileInputStream fis = new FileInputStream(srcFile);
    FileOutputStream fos = new FileOutputStream(destFile);
    //定义一个缓冲区。
    byte[] buf = new byte[1024];
    int len = 0;
    while ((len = fis.read(buf)) != -1) {
        fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
    }
    fos.close();
    fis.close();
}
  1. 使用缓冲流复制文件(效率更快)
public static void main(String[] args) throws IOException {
    BufferedReader in = new BufferedReader(new FileReader("D:/Plan.txt"));
    BufferedWriter ou = new BufferedWriter(new FileWriter("C:/Plan.txt"));
	
    String line = null;
    while( ( line = in.readLine() ) != null) {
	ou.write(line);
	ou.newLine();
    }
    ou.close();
    in.close();
}


字符流

字符流

Reader(抽象)(字符输入流)

Reader是所有字符输入流的抽象基类,把输入流中的字符读到内存中

基本方法:

read() //从文件中读取下一字符
read(char[]) //从文件中读取一定数量字符到数组中

注:当读取不到字符会返回 -1


BufferedReader

该流能缓冲各个字符,从而提供字符、数组、字符串的高效读取

构造方法:

  1. 需要实例化一个File文件对象
    • BufferedReader( FileReader )

使用方式

常用特性方法:

  • readLine() ——没有则返回 null
    BufferedReader in = new BufferedReader(new FileReader("file.txt"));

    String line = null;
    while( (line = in.readLine()) != null ){
        System.out.println(line);
    }
    in.close();

InputStreamReader(输入转换流)

使用指定编码表,将输入的“字节”转换成“字符”的输入流

使用方法

public static void readC() throws IOException{
    //创建读取文件的字节流对象
    InputStream in = new FileInputStream("c:\\c.txt");
    
    //创建转换流对象 
    //这样创建对象,会用本地默认码表读取,将会发生错误解码的错误
    //InputStreamReader isr = new InputStreamReader(in);
    InputStreamReader isr = new InputStreamReader(in,"utf-8");
    
    //使用转换流去读字节流中的字节
    int ch = 0;
    while((ch = isr.read())!=-1){
    	System.out.println((char)ch);
    }
    isr.close();
}

注意:一旦要指定其他编码时,绝对不能用子类(FileReader),必须用该转换流

其实在FileReader使用的时候:

    FileReader fr = new FileReader("a.txt");

这里就使用的是默认编码表


FileReader

这个类就是上面所说的简化而来的子类,能方便快捷地读取文件字符

构造方法:

  1. 需要实例化一个File文件对象
    • FileReader( File )
  2. 无需手动实例化File文件对象
    • FileReader( String )

使用方式

public static void readText() throws IOException {
    FileReader fr = new FileReader("E:\\test\\a.txt");
    int ch = 0;
    while((ch = fr.read())!=-1){
        //输出的字符对应的编码值
        System.out.println(ch);
        //输出字符本身
        System.out.println((char)ch);
    }
}

Writer(抽象)(字符输出流)

OutputStream是所有字符输出流的抽象基类,提供内存字符输出到文件的通用方法

基本方法:

write( int ) //将单个字符写入输出流
write( char[] ) //将一定数量字符数组写入输出流
write( char[] , int , int ) //将指定数组指定位置数量写入输出流
write( String ) //将字符串写入输出流
write( String , int , int) //将字符串一部分写入输出流

注:如果文件不存在,则会创建该文件,如果存在,则覆盖


BufferedWriter

缓冲各个字符,从而提供字符、数组、字符串的高效读取

构造方法:

  • BufferedWriter( FileWriter )

使用方式
常用特性方法:

  • readLine() ——没有则返回 null
    FileWriter fileOut = new FileWriter("file.txt");
    BufferedWriter out = new BufferedWriter(fileOut);
    for (int i=0; i<5; i++) {
        out.write("hello");
        out.newLine();
    }
    out.close();

OutputStreamWriter(输出转换流)

使用指定编码表,将“字符”转换成“字节”的输出流,再使用字节流写出去

public static void writeC() throws Exception {
    //创建与文件关联的字节输出流对象
    FileOutputStream fos = new FileOutputStream("c:\\c.txt");
    //创建可以把字符转成字节的转换流对象,并指定编码
    OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
    //调用转换流,把文字写出去,其实是写到转换流的缓冲区中
    osw.write("你好");//写入缓冲区。
    osw.close();
}

注:当调用 write 方法时,流会将字符在码表进行查询,转成字节后存到缓冲区中


FileWriter

功能性同FileReader相似,是简化父类操作的字符输出流,方便地将字符写到文件中

构造方法有四个:

  1. 需要实例化一个File文件对象
    • FileWriter( File )
    • FileWriter( Fileboolean )
  2. 无需手动实例化File文件对象
    • FileWriter( String )
    • FileWriter( String , boolean )

boolean代表是否在文件末位继续添加(不覆盖)

使用方法

public static void main(String[] args) throws IOException {
    //演示FileWriter 用于操作文件的便捷类。
    FileWriter fw = new FileWriter("E:\\text\\fw.txt");
    fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。
    fw.flush();//刷新
    fw.close();// 关闭之前需要刷新它
}

注意:在写入字符的时候,需要先进行流的刷新,再关闭流


练习
  1. 使用字符流复制文本文件
public static void copyTextFile() throws IOException {
	//1,明确源和目的。
	FileReader fr = new FileReader("c:\\a.txt");
	FileWriter fw = new FileWriter("c:\\copy.txt");
	//2,为了提高效率。自定义缓冲区数组。字符数组。
	char[] buf = new char[1024];
	int len = 0;
	while((len=fr.read(buf))!=-1){
            fw.write(buf,0,len);
	}
	//3,关闭资源。
	fw.close();
	fr.close();
}
  1. 使用缓冲流复制文件(效率更快)
public static void main(String[] args) throws IOException {
	//1,指定数据源, 是数据源中读数据,采用输入流
	BufferedReader in = new BufferedReader(new FileReader("file.txt"));
	//2,指定目的地,是把数据写入目的地,采用输出流
	BufferedWriter out = new BufferedWriter(new FileWriter("copy.txt"));
	//3,读数据
	String line = null;
	while ( (line = in.readLine()) != null ) {
		//4,写数据
		out.write(line);
		//写入换行符号
		out.newLine();
	}
	//5,关闭流
	out.close();
	in.close();
}


还有一些常用IO

由于想偷懒,就直接总结了

Properties集合

  • 表示的是一个持久的属性集
  • 属性列表是个键值对
  • 每个键及其对应值都是一个String
  • 哈希表的子类map集合 中的方法都可以使用
  • 键值对可以存储到集合中,也可以存到持久化设备中
基本方法
setProperty( String , String ) //设置键值对到集合中
getProperty( String ) //从键值对中根据指定的键获取值

与流技术相结合的方法:

load( InputStream ) //从输入流中读取属性键值对
load( Reader ) //按行的格式从字符流中读取属性键值对
store( OutputStream , String ) //以字节输出方法格式,将属性键值对写入输出流
store( Writer , String ) //以字符输出方法格式,将属性键值对写入输出流

(第二个参数String是写入文件中附带的注释)

使用方式

将集合中的内容存储到文件中:

public static void main(String[] args) throws IOException {
	//1,创建Properties集合
	Properties prop = new Properties();
	//2,添加元素到集合
	prop.setProperty("周迅", "张学友");
	prop.setProperty("李小璐", "贾乃亮");
	prop.setProperty("杨幂", "刘恺威");
	
	//3,创建流
	FileWriter out = new FileWriter("prop.properties");
	//4,把集合中的数据存储到流所对应的文件中
	prop.store(out, "save data");
	//5,关闭流
	out.close();
}

将文件中的数据读取到集合中:

public static void main(String[] args) throws IOException {
	//1,创建集合
	Properties prop = new Properties();
	//2,创建流对象
	FileInputStream in = new FileInputStream("prop.properties");
    	//FileReader in = new FileReader("prop.properties");
	//3,把流所对应文件中的数据 读取到集合中
	prop.load(in);
	//4,关闭流
	in.close();
	//5,显示集合中的数据
	System.out.println(prop);
}

反序列化流

  • 反序列化的对象必须要提供该对象的字节码文件
  • 序列化接口声明的序列UID号不一致会报错
ObjectInputStream(反序列化)

对以前序列化的对象从流中进行读取

构造方法:

  • ObjectInputStream( InputStream )

基本方法:

  • readObject( ) ——从反序列化流中读取对象
使用方式:
public static void readObj() throws IOException, ClassNotFoundException {
    //1,定义流对象关联存储了对象文件
    FileInputStream fis = new FileInputStream("tempfile\\obj.object");
    //2,建立用于读取对象的功能对象
    ObjectInputStream ois = new ObjectInputStream(fis);
    Person obj = (Person)ois.readObject();

    System.out.println(obj.toString());
}

序列化流

  • 这是专门用于操作对象的流,将对象存储到磁盘、网络中
  • JavaBean对象都需要做序列化
ObjectOutputStream(序列化)

将对象基本数据类型和图形写入字节输出流

构造方法:

  • ObjectOutputStream( OutputStream )

基本方法:

  • writerObject( Object ) ——写入指定对象
使用方式:
public static void writeObj() throws IOException {
    //1,明确存储对象的文件
    FileOutputStream fos = new FileOutputStream("tempfile\\obj.object");
    //2,给操作文件对象加入写入对象功能
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    //3,调用了写入对象的方法
    oos.writeObject(new Person("wangcai",20));
    //关闭资源
    oos.close();
}

打印流

输出信息最方便的类,能打印各种数据值

构造方法:

字节打印流 字符打印流
PrintStream( File ) PrintWriter( File )
PrintStream( OutputStream ) PrintWriter( OutputStream )
PrintStream( OutputStream , boolean ) PrintWriter( OutputStream , boolean )

基本方法:

print( ) //此方法被重载多次,输出任意数据
println( ) //输出任意数据后换行
printf( ) //根据本地环境格式化输出

注:

System.out.println();

//其实等价于
PrintStream ps = new PrintWriter(System.out);
ps.println();
使用方式:
public static void main(String[] args) throws IOException {
    //创建流
    //PrintWriter out = new PrintWriter("printFile.txt");//无自动刷新
    PrintWriter out = new PrintWriter(new FileWriter("printFile.txt"), true);

    //2,写数据
    for (int i=0; i<5; i++) {
        out.println("helloWorld");
    }
    //3,关闭流
    out.close();
}

NIO(管道流)

  • 管道流主要由 缓冲区(Buffer)管道(Channel) 两部分组成
  • 数据必须先读入缓冲区再进行处理
NIO 与 普通IO的区别:
  1. NIO面向缓冲;IO面向流
  2. NIO是非阻塞的;IO是阻塞IO
  3. NIO有其选择器
使用方式
public static void main(String[] args) throws Exception {
    File file = new File("E:\\work\\TestFile\\s.avi");
    FileInputStream fis = new FileInputStream(file);
	
    FileOutputStream fos = new FileOutputStream("E:\\work\\TestFile\\ss.avi");
    // 用字节流获取文件通道
    FileChannel in = fis.getChannel();
    FileChannel ot = fos.getChannel();
    	
    // 分配一个新的字节缓冲区,内容放在缓冲区里面,不能大也不能小
    ByteBuffer allocate = ByteBuffer.allocate((int)file.length());
    	
    // 读缓冲区的内容
    in.read(allocate);
    	
    // 查看指针的位置
    System.out.println(allocate.position());
    // 把指针设置为0
    allocate.flip();
    // 写缓冲区的内容到指定的位置
    ot.write(allocate);
    
    in.close();
    ot.close();
    fis.close();
    fos.close();
}

随机流

  • 该随机访问文件流可以在文件任意地方写入数据任意地方读取字节
构造方法
  1. 需要实例化一个File文件对象
    • RandomAccessFile( File , String )
  2. 无需手动实例化File文件对象
    • RandomAccessFile( String , String )

第二个String参数是mode,指定打开文件的访问模式

  • " r " :只读
  • " rw ":读写
  • " rws ":数据会立即写入文件,以防异常
  • " rwd ":已被write的数据会保存到文件

随机流适合用于分文件复制断点网络下载


使用IO进行网络下载

public static void main(String[] args) throws Exception {
	// 目的地
	File savefile = new File("F:/fileTest/b.jpg");
	String src = "http://tupian.aladd.net/2013/11/738.jpg";
	long filelength = 0;
	if(savefile.exists()){
		filelength = savefile.length();
	}
	else{
		filelength=0;
	}
	//创建url对象
	URL url = new URL(src);
	//建立远程连接
	URLConnection connection= url.openConnection();
	//建立Http请求的连接
	HttpURLConnection hc = (HttpURLConnection) connection;
	//设置请求消息
	hc.setRequestProperty("Range", "bytes="+filelength+"-");
	//读
	InputStream is= hc.getInputStream();
	BufferedInputStream bis = new BufferedInputStream(is);
	//写
	FileOutputStream bos = new FileOutputStream(savefile,true);
	byte buff[] = new byte[1024*8];
	int i ;
	while((i=bis.read(buff))!=-1){
		bos.write(buff,0,i);
	}
	bis.close();
	bos.close();
}


posted @ 2019-08-25 20:12  鹿友  阅读(216)  评论(0编辑  收藏  举报