Java I/O文件处理

字节流与字符流

字节输出流OutputStream

  • public abstract class OutputStream
    extends Object
    implements Closeable, Flushable
    这个抽象类是表示字节输出流的所有类的超类。 输出流接收输出字节并将其发送到某个接收器。

    需要定义OutputStream子类的应用OutputStream必须至少提供一个写入一个字节输出的方法。

初始化:

		File file = new File("文件路径");
		OutputStream out = null;
		out = new FileOutputStream(file);
//		out = new FileOutputStream(file, true);  // 追加新内容的初始化

字节输入流InputStream:

  • public abstract class InputStream
    extends Object
    implements Closeable
    这个抽象类是表示输入字节流的所有类的超类。

    需要定义InputStream子类的应用InputStream必须始终提供一种返回输入的下一个字节的方法。

初始化字节输入流:

		File file = new File("文件路径");
		InputStream input = null;
		input = new FileInputStream(file);

字符流:

字符输出流Writer:

  • public abstract class Writer
    extends Object
    implements Appendable, Closeable, Flushable

    用于写入字符流的抽象类。 子类必须实现的唯一方法是write(char [],int,int),flush()和close()。 然而,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率,附加的功能或两者。

字符输出流初始化:

		File file = new File("文件路径");
		Writer out = null;
		out = new FileWriter(file);
//		out = new FileWriter(file, true); //  追加内容

字符输入流Reader:

  • public abstract class Reader
    extends Object
    implements Readable, Closeable

    用于读取字符流的抽象类。 子类必须实现的唯一方法是read(char [],int,int)和close()。 然而,大多数子类将覆盖这里定义的一些方法,以便提供更高的效率,附加的功能或两者。

字符输入流初始化

		File file = new File("文件路径");
		Reader input = null;
		input = new FileReader(file);

字节转换流:OutputStreamWriter将字节转变为字符流

  • public class OutputStreamWriter
    extends Writer
    OutputStreamWriter是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节charset 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

    每次调用write()方法都会使编码转换器在给定字符上被调用。 所得到的字节在写入底层输出流之前累积在缓冲区中。 可以指定此缓冲区的大小,但是默认情况下它大部分用于大多数目的。 请注意,传递给write()方法的字符不会缓冲。

    为了最大的效率,请考虑在BufferedWriter中包装一个OutputStreamWriter,以避免频繁的转换器调用。 例如:

      Writer out
       = new BufferedWriter(new OutputStreamWriter(System.out)); 

初始化:

		File file = new File("文件路径");
		Writer out = null;
		out = new OutputStreamWriter(new FileOutputStream(file));

InputStreamWriter

  • public class InputStreamReader
    extends Reader
    InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。 它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。

    每个调用InputStreamReader的read()方法之一可能会导致从底层字节输入流读取一个或多个字节。 为了使字节有效地转换为字符,可以从底层流读取比满足当前读取操作所需的更多字节。

    为了最大的效率,请考虑在BufferedReader中包装一个InputStreamReader。 例如:

      BufferedReader in
       = new BufferedReader(new InputStreamReader(System.in)); 

初始化:

		File file = new File("文件路径");
		Reader input = null;
		input = new InputStreamReader(new FileInputStream(file));

不管是字节流还是字符流,实际上最终都是以字节的形式操作输入/输出流的

 

内存操作流:ByteArrayInputStream、ByteArrayOutputStream

ByteArrayInputStream

  • public class ByteArrayInputStream
    extends InputStream
    A ByteArrayInputStream包含一个内部缓冲区,其中包含可以从流中读取的字节。 内部计数器跟踪read方法要提供的下一个字节。

    关闭ByteArrayInputStream没有任何效果。 在关闭流之后,可以调用此类中的方法,而不生成IOException 。

ByteArrayOutputStream

  • public class ByteArrayOutputStream
    extends OutputStream
    该类实现了将数据写入字节数组的输出流。 当数据写入缓冲区时,缓冲区会自动增长。 数据可以使用toByteArray()toString()

    关闭ByteArrayOutputStream没有任何效果。 该流中的方法可以在流关闭后调用,而不生成IOException 。

管道流:实现两个线程之间的通信

PipedInputStream

  • public class PipedInputStream
    extends InputStream

    管道输入流应连接到管道输出流; 管道输入流然后提供写入管道输出流的任何数据字节。

构造方法:

基本方法:

PipedOutputStream

  • public class PipedOutputStream
    extends OutputStream

    管道输出流可以连接到管道输入流以创建通信管道。 管道输出流是管道的发送端。

构造方法:

基本方法:

import java.io.PipedOutputStream;

class Send implements Runnable {
	private PipedOutputStream pos = null;

	public Send() {
		this.pos = new PipedOutputStream();
	}

	public void run() {
		String str = "We would love to fritter away our days";
		try {
			this.pos.write(str.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			this.pos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public PipedOutputStream getPos() {
		return this.pos;
	}

}
import java.io.PipedInputStream;

public class Receive implements Runnable {
	private PipedInputStream pis = null;

	public Receive() {
		this.pis = new PipedInputStream();
	}

	public void run() {
		byte b[] = new byte[1024];
		int len = 0;
		try {
			len = this.pis.read(b);
		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			this.pis.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("接收内容:" + new String(b, 0, len));
	}

	public PipedInputStream getPis() {
		return this.pis;
	}

}

public class Test {

	public static void main(String[] args) {
		Send send = new Send();
		Receive receive = new Receive();
		try {
			send.getPos().connect(receive.getPis()); // 连接管道
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		new Thread(send).start();
		new Thread(receive).start();

	}

}

 

 

压缩流

import java.io.*;
import java.util.zip.*;

class ZipCompress {

	public static void main(String[] args) {
		ZipCompress zipCom = new ZipCompress("C:\\Users\\fuchen\\Desktop\\新建文件夹.zip", "E:\\成长ing\\文档\\文档");
		try {
			zipCom.zip();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String zipFileName; // 目的地Zip文件
	private String sourceFileName; // 源文件(带压缩的文件或文件夹)

	public ZipCompress(String zipFileName, String sourceFileName) {
		this.zipFileName = zipFileName;
		this.sourceFileName = sourceFileName;
	}

	public void zip() throws Exception {
		// File zipFile = new File(zipFileName);
		System.out.println("开始压缩:");

		// 创建zip输出流
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));

		// 创建缓冲输出流
		BufferedOutputStream bos = new BufferedOutputStream(out);

		File sourceFile = new File(sourceFileName);

		// 调用函数
		compress(out, bos, sourceFile, sourceFile.getName());

		bos.close();
		out.close();
		System.out.println("压缩完成");

	}

	public void compress(ZipOutputStream out, BufferedOutputStream bos, File sourceFile, String base) throws Exception {
		// 如果路径为目录(文件夹)
		if (sourceFile.isDirectory()) {

			// 取出文件夹中的文件(或子文件夹)
			File[] flist = sourceFile.listFiles();

			if (flist.length == 0)// 如果文件夹为空,则只需在目的地zip文件中写入一个目录进入点
			{
				System.out.println(base + File.separator);
				out.putNextEntry(new ZipEntry(base + File.separator));
			} else { // 如果文件夹不为空,则递归调用compress,文件夹中的每一个文件(或文件夹)进行压缩
				for (int i = 0; i < flist.length; i++) {
					compress(out, bos, flist[i], base + File.separator + flist[i].getName());
				}
			}
		} else { // 如果不是目录(文件夹),即为文件,则先写入目录进入点,之后将文件写入zip文件中
			out.putNextEntry(new ZipEntry(base));
			FileInputStream fos = new FileInputStream(sourceFile);
			BufferedInputStream bis = new BufferedInputStream(fos);
			int tag;
//			System.out.println(base + " source " + sourceFile);
			System.out.println(base);
			// 将源文件写入到zip文件中
			while ((tag = bis.read()) != -1) {
				bos.write(tag);
			}
			bis.close();
			fos.close();
		}
	}
}

 

对象序列化:

Serializable接口定义(当前该接口中暂无任何的方法,只对需要序列化的类实现该接口,避免以后该接口扩展导致需要大量的修改),序列化还需要依靠对象输入输出流来完成

public interface Serializable{}

对象输出流:ObjectPutputStream定义格式

public class ObjectOutputStream extends OutputStream
    implement ObjectOutput, ObjetStreamConstants

两个常用的方法:

public ObjectOutputStream(OutputStream out) throws IOException // 构造方法,传入输出的对象
public final void writeObject(Object obj) throws IOException //普通方法,输出对象

对象输入流:ObjectInputStream定义格式

public class ObjectInputStream extends InputStream
    implements ObjectInput, ObjectStreamConstants

两个常用方法:

public ObjectInputStream(InputStream in) throws IOException //构造方法,构造输入对象
public final Object readObject() throws IOException, ClassNotFoundException //普通方法,从指定位置读取对象
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class IoStream {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		File file = new File("E:" + File.separator + "test.txt");
		ObjectOutputStream oos = null;
		OutputStream out = new FileOutputStream(file);
		oos = new ObjectOutputStream(out);
		oos.writeObject(new Person("浮沉"));
		oos.close();
		
		ObjectInputStream ois = null;
		InputStream input = new FileInputStream(file);
		ois = new ObjectInputStream(input);
		Object obj = ois.readObject();
		ois.close();
		System.out.println(obj);
	}

	static class Person implements Serializable {
		private static final long serialVersionUID = 1L;
		private String name;

		public Person() {
		}

		public Person(String name) {
			this.setName(name);
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
		
		@Override
		public String toString() {
			return "姓名:" + this.name;
		}

	}

}

 

Externalizable接口定义:

public interface Externalizable extends java.io.Serializable {
    void writeExternal(ObjectOutput out) throws IOException; 
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}

被Serializable接口声明的类的对象都就将被序列化,(Externalizable接口可以实现指定序列化内容)

writeExternal(ObjectOutput out):此方法中指定要保存的属性的信息,对象序列化时调用

readExternal(ObjectInput in):在此方法中读取被保存的信息,对象反序列化时调用

(这里留作补上调用的代码)

关键字:transient,设置某个属性不被序列化

 

序列化一组对象

在Java对象输出时只提供了一个对象的输出操作(writeObject (Object obj)),并没有提供多个对象的输出,同时序列化多个对象,需使用对象数组进行操作(因为数组属于引用类型,可以直接使用Object类型接收)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class z {
	
	public static void ser(Object obj[]) throws IOException {
		File file = new File("E:" + File.separator + "test.txt");
		ObjectOutputStream oos = null;  // 声明对象输出流
		OutputStream out = new FileOutputStream(file);  // 文件输出流
		oos = new ObjectOutputStream(out);
		oos.writeObject(obj);
		oos.close();
	}

	public static Object[] dser() throws ClassNotFoundException, IOException {
		File file = new File("E:" + File.separator + "test.txt");
		ObjectInputStream ois = null;  // 声明对象输入流
		InputStream input = new FileInputStream(file);  // 文件输入流
		ois = new ObjectInputStream(input);  // 实例化对象输入流
		Object obj[] = (Object[])ois.readObject();  // 读取对象
		ois.close();
		return obj;
	}
}

 

新增的I/O

使用buffer(缓冲区)

Buffer是一个抽象类,可以在底层字节数组上进行get/set操作,除了boolean外,其他的基本类型都有相应的Buffer类

static XxxBuffer allocate(int capacity) // 创建一个容量为capacity的XxxBuffer对象

Buffer中有三个概念:

1、容量(capacity):缓冲区的容量表示该Buffer的最大数据容量,即最多可以存储多少数据

2、界限(limit):第一个不应该被读出或者写入的缓冲区位置索引。(位于limit后的数据不可以被读写)

3、位置(position):用于指明下一个被读写的缓冲区位置索引(类似于I/O流的指针)

Buffer中还可以有一个mark,mark的作用是允许程序直接将poition定位到mark处。

以上四者满足:0 <= mark <= position <= limit <= capacity

Buffer常用方法:

int capacity() // 返回Buffer的capacity大小
boolean hasRemaining() // 判断当前位置和界限之间是否还有元素可供处理
int limit() // 放回Buffer的界限位置
Buffer limit(int newLimit) // 重新设置界限的值,并放回一个行的limit的缓冲区对象
Buffer mark() // 设置Buffer的mark位置,它只能在0和位置(position)之间做mark
int position() // 返回Buffer中的当前位置
Buffer position(int newPs) // 设置Buffer的新位置,并放回一个具有改变position后的Buffer对象
int remaining() // 返回当前位置和界限之间的元素个数
Buffer reset() // 将位置转到mark所在的位置
Buffer rewind() // 将位置设置为0,取消设置的mark

Channel:

Java的Channel类类似于传统的流对象,但与传统的流相比,主要有两点区别:

(1)Channel可以直接将指定文件的部分或全部直接映射成Buffer

(2)程序不能直接访问Channel中的数据,Channel只能与Buffer进行交互

Channel中常用的三类方法是map、read、write,其中map()方法用于将Channel对应的部分或全部数据映射到ByteBuffer,而read()和write()方法都有一系列重载形式,map方法签名

// 第一个参数执行映射时的模式,分别只只读和读写等模式,第二、第三个参数用于控制那些数据映射成ByteBuffer
MappedByteBuffer map(FileChannel.MapMode mode, long position, long size) 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值