IO流续,NIO

基本数据类型流

数据输入流:DataInputStream

数据输出流:DataOutputStream

特点

1.该流是一个字节流,可以读写字节的同时,还能够读写基本数据类型
2.通过数据类型输出流写入到文件中,使用文本文件打开是不能阅读,提高了基本数据类型在文件中保存的安全性
3.读的时候必须和写的顺序保持一致,提高了基本数据类型在文件中保存的安全性

    public static void main(String[] args) throws Exception {
    //		write();
    //		read();
    //		copy("dos.txt", "copy.txt");
            copy2("dos.txt", "copy2.txt");
            copy3("dos.txt", "copy3.txt");
        }

        private static void copy3(String srcFileName, String descFileName) throws Exception {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFileName));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFileName));

            int len = 0;
            byte[] bys = new byte[1024];

            while ((len = bis.read(bys)) != -1) {
                bos.write(bys, 0, len);
                bos.flush();
            }

            bis.close();
            bos.close();
        }

        private static void copy2(String srcFileName, String descFileName) throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(srcFileName));
            BufferedWriter bw = new BufferedWriter(new FileWriter(descFileName));

            int len = 0;
            char[] chs = new char[1024];

            while ((len = br.read(chs)) != -1) {
                bw.write(chs, 0, len);
                bw.flush();
            }

            br.close();
            bw.close();

        }

        private static void copy(String srcFileName, String descFileName) throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(srcFileName));
            BufferedWriter bw = new BufferedWriter(new FileWriter(descFileName));

            String line = null;
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }

            br.close();
            bw.close();
        }



        private static void read() throws Exception {
            DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));
            byte by = dis.readByte();
            short s = dis.readShort();
            int i = dis.readInt();
            long l = dis.readLong();
            float f = dis.readFloat();
            double d = dis.readDouble();
            char ch = dis.readChar();
            boolean bool = dis.readBoolean();
            System.out.println(by);
            System.out.println(s);
            System.out.println(i);
            System.out.println(l);
            System.out.println(f);
            System.out.println(d);
            System.out.println(ch);
            System.out.println(bool);
            dis.close();
        }

        private static void write() throws Exception {
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));
            dos.writeByte(10);
            dos.writeShort(20);
            dos.writeInt(30);
            dos.writeLong(40);
            dos.writeFloat(2.5f);
            dos.writeDouble(3.5);
            dos.writeChar('a');
            dos.writeBoolean(false);
            dos.close();
        }
    }

打印流PrintWriter

向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有
print 方法

特点

1.只能写数据,不能读取数据。
2.可以操作任意类型的数据。
3.如果启动了自动刷新,能够自动刷新。(启用了自动刷新,只有在调用 printlnprintfformat 的其中一个方法时才可能完成自动刷新操作)

    public class IODemo02 {

        public static void main(String[] args) throws Exception {
            PrintWriter pw = new PrintWriter(new FileWriter("pw.txt"), true);
    //		pw.write("abc");
    //		pw.write("efg");
    //		pw.flush();
    //		pw.close();

    //		pw.print("abc");
    //		pw.flush();
    //		pw.println("hello");
    //		pw.flush();
    //		pw.println("world");
    //		pw.flush();

    //		pw.println("good");
    //		pw.format("我叫做%s,我今年%d", "隔壁老王",20);

    //		copy();
            copy2("test.txt", "demo3.txt");
        }

        private static void copy3(String srcFileName, String descFileName) throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(srcFileName));
            BufferedWriter bw = new BufferedWriter(new FileWriter(descFileName));

            String line = null;
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }

            br.close();
            bw.close();
        }


        private static void copy(String srcFileName, String descFileName) throws Exception{
            BufferedReader br = new BufferedReader(new FileReader(srcFileName));
            PrintWriter pw = new PrintWriter(new FileWriter(descFileName));

            int len = 0;
            char[] chs = new char[1024];

            while ((len = br.read(chs)) != -1) {
                pw.write(chs, 0, len);
                pw.flush();
            }

            br.close();
            pw.close();

        }

        private static void copy2(String srcFileName, String descFileName) throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(srcFileName));
            PrintWriter pw = new PrintWriter(new FileWriter(descFileName), true);

            String line = null;
            while ((line = br.readLine()) != null) {
                pw.println(line);
            }

            br.close();
            pw.close();
        }


    }

输入输出流

System类中的静态变量:in,out 。

“标准”输入流:static InputStream in 。

“标准”输出流:static PrintStream out 。

它们各代表了系统标准的输入和输出设备。

默认输入设备是键盘,输出设备是显示器。

public class IODemo03 {
	public static void main(String[] args) throws IOException {
//		PrintStream ps = System.out;
//		ps.append("hello");
//		
//		System.out.println("HelloWorld");
//		
//		ps.println(new Object());
//		
//		PrintStream ps2 = System.err;
//		ps2.println("great");
		
//		InputStream in = System.in;
//		byte[] bys = new byte[10];
//		int len = in.read(bys);
//		System.out.println(new String(bys, 0, len));
		
		// java.util.InputMismatchException
//		Scanner input = new Scanner(System.in);
//		double d = input.nextDouble();
//		System.out.println(d);
		
//		InputStream in = System.in;
//		InputStreamReader isr = new InputStreamReader(in);
//		BufferedReader br = new BufferedReader(isr);
//		System.out.print("请输入数据:");
//		String line = br.readLine();
//		double d = Double.parseDouble(line);
//		System.out.println("您输入的数据是: " + d);
		
		MyScanner input = new MyScanner(System.in);
		System.out.print("请输入字符串: ");
		String line = input.nextLine();
		System.out.println("数据: " + line);
		
		System.out.print("请输入小数: ");
		double d = input.nextDouble();
		System.out.println("小数: " + d);
	}
}

// 自定义一个类似于Scanner类
class MyScanner {
	// 通过外界传入输入流
	private InputStream is;
	
	public MyScanner() {}
	
	public MyScanner(InputStream is) {
		this.is = is;
	}
	
	public String nextLine() {
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		try {
			String line = br.readLine();
			return line;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public double nextDouble() throws InputMismatchException {
		String line = this.nextLine();
		try {
			double d = Double.parseDouble(line);
			return d;
		} catch (NumberFormatException e) {
			throw new InputMismatchException("hey! 你要输入小数啊!!!!");
		}
	}
}

序列化流

序列化流ObjectOutputStream

反序列化流ObjectInputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。

注意:类需要通过实现 java.io.Serializable 接口启用其序列化功能,不实现此接口的类将无法使其任何状态序列化或反序列化

注意:序列化数据后,再次修改类文件,读取数据会出问题,是因为序列化id发生了变化,解决办法就是给类自定义一个id。

如果其中的某些成员变量不需要序列化可使用transient关键字声明

public class IODemo04 {
	public static void main(String[] args) throws IOException, Exception {
//		write();
		read();
	}

	private static void read() throws Exception {
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
		Object obj = ois.readObject();
		if (obj instanceof Student) {
			Student s = (Student) obj;
			System.out.println(s.getName() + "|" + s.getAge());
		}
		ois.close();
	}

	private static void write() throws Exception, IOException {
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
		oos.writeObject(new Student("隔壁老王", 30));
		oos.close();
	}
}

class Student implements Serializable {
	private static final long serialVersionUID = 7512677611218988631L;
	String name;
	private transient int age; // 防止该成员变量序列化到文件中
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	
}

Properties

Properties 类表示了一个持久的属性集;Properties 可保存在流中或从流中加载;属性列表中每个键及其对应值都是一个字符串。

Properties可以当做Map集合类使用

public Object setProperty(String key,String value)

public String getProperty(String key)

public Set stringPropertyNames()

Properties和IO流结合使用

public void load(Reader reader)

public void store(Writer writer,String comments)

public class IODemo06 {
	static Properties prop;
	static {
		prop = new Properties();
		try {
			prop.load(new FileReader("config/prop.properties"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void main(String[] args) throws FileNotFoundException, IOException {
		// 当做map来使用
//		Properties prop = new Properties();
//		prop.put("hello1", "world1");
//		prop.put("hello2", "world2");
//		prop.put("hello3", "world3");
//		
//		Set<Object> keys = prop.keySet();
//		for (Object obj : keys) {
//			System.out.println(obj);
//		}
		
		// 当做特殊的属性集使用
		/*
		 *  public Object setProperty(String key,String value)
			public String getProperty(String key)
			public Set<String> stringPropertyNames()
		 */
//		Properties prop = new Properties();
//		prop.setProperty("hello1", "world1");
//		prop.setProperty("hello2", "world2");
//		prop.setProperty("hello3", "world3");
//		
//		Set<String> keys = prop.stringPropertyNames();
//		for (String key : keys) {
//			String value = prop.getProperty(key);
//			System.out.println(key + "=" + value);
//		}
		
		// 当做流使用
		/*
		 * Properties和IO流结合使用
			public void load(Reader reader)
			public void store(Writer writer,String comments)
		 */
//		System.out.println(prop);
		prop.store(new FileWriter("config/prop2.properties"), "comments");
	}
}

NIO

NIO在JDK1.4后引入的,NIO是面向块(缓冲区)编程,旧IO是面向流编程

Buffer

Buffer是一个抽象类,针对缓冲区封装的一个类,提供相应的方法来操作这个缓冲区

子类有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer

核心类

ByteBuffer和CharBuffer

ByteBuffer有一个子类 MappedByteBuffer

MappedByteBuffer类能够将文件直接映射到内存中,那么这样我们就可以像访问内存一样访问文件,非常方便

获取Buffer

static ByteBuffer allocate(int capacity) 分配一个新的字节缓冲区。

static ByteBuffer allocateDirect(int capacity) 分配新的直接字节缓冲区。

二者获取Buffer的区别

1.创建普通Buffer成本低,读写的效率不高
2.因为创建直接Buffer成本高,所以我们一般用在Buffer生存周期较长的时候使用
3.只有ByteBuffer才能够创建直接Buffer,其他的Buffer对象是不能够创建
4.如果创建了直接Buffer但是我又想要使用其他Buffer的功能,可以将ByteBuffer转换成其他Buffer
asIntBuffer()

常用方法

flip(): 将写模式切换为读模式, 将limit的值改为postion的值,同时将postion归0,就是为下一次数据的读取做好准备

clear(): 将读模式切换为写模式,将limit改为capacity的值,同时将postion归0,就是为下一次数据的写入做好准备

put(): 相对读取,向Buffer中存储数据

get(): 相对读取,从Buffer中获取数据

mark(): 设置标记位

reset(): 重置

hasRemaining(): 判断当前位置和limit之间是否还有元素可处理

get(index) 绝对读取,不会影响position的位置

put() get() 相对读取,会影响position的位置,每次读取一次,指针后移

public class NIoDemo01 {

	public static void main(String[] args) {
		ByteBuffer buffer = ByteBuffer.allocateDirect(10);
		CharBuffer charBuffer =buffer.asCharBuffer();
		//capactiy:定义缓冲区的容量 这里charBuffer容量为5是因为byteBuffer的容量为10
		System.out.println("capacity:"+charBuffer.capacity());
		//limit:无效缓冲区的第一个位置索引,limit后面的数据既不可读,也不可写
		//因为这个缓冲区的大小为5所以limit为5
		System.out.println("limit:"+charBuffer.limit());
		//mark:标记索引,该索引能够用于下次读取或者写入,它只能够在0-position之间
		//这里没有标记所以没有
		System.out.println("mark:"+charBuffer.mark());
		//position:下一个可以被读取或者写入的缓冲区位置索引
		//每写入一个position往后移一位
		System.out.println("position:"+charBuffer.position());
		
		charBuffer.put('a');
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		charBuffer.put('b');
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		charBuffer.put('c');
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		charBuffer.put('d');
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		charBuffer.put('e');
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
//		charBuffer.put('b');//抛出java.nio.BufferOverflowException
//		System.out.println("---------------------------------------");
//		System.out.println("capacity:"+charBuffer.capacity());
//		System.out.println("limit:"+charBuffer.limit());
//		System.out.println("mark:"+charBuffer.mark());
//		System.out.println("position:"+charBuffer.position());
		
		charBuffer.clear();//切换为读模式同时将position置零
		System.out.println("---------------------------------------");
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		
		System.out.println("---------------------------------------");
		System.out.println(charBuffer.get());
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		System.out.println("---------------------------------------");
		System.out.println(charBuffer.get());
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		System.out.println("---------------------------------------");
		System.out.println(charBuffer.get());
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		System.out.println("---------------------------------------");
		System.out.println(charBuffer.get());
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		System.out.println("---------------------------------------");
		System.out.println(charBuffer.get());
		System.out.println("capacity:"+charBuffer.capacity());
		System.out.println("limit:"+charBuffer.limit());
		System.out.println("mark:"+charBuffer.mark());
		System.out.println("position:"+charBuffer.position());
		
		//抛出java.nio.BufferUnderflowException
//		System.out.println("---------------------------------------");
//		System.out.println(charBuffer.get());
//		System.out.println("capacity:"+charBuffer.capacity());
//		System.out.println("limit:"+charBuffer.limit());
//		System.out.println("mark:"+charBuffer.mark());
//		System.out.println("position:"+charBuffer.position());
	}

}
Channel

Channel原理类似于传统的流对象, FileInputStream FileOutputStream

但是Channel与传统的流对象有3个主要的区别

1.程序如果想要读取Channel中的数据,不能够直接读写,必须经过Buffer 【唯一性】

2.通过Channel通道既能够读取也能够写入数据 【双向性】

3.Channel能够将指定的部分或者全部文件映射到内存中

Java中为Channel提供了如下常用的类

FileChannel 和文件相关的通道

DatagramChannel 和UDP协议传输数据相关的通道

SocketChannel 针对TCP协议客户端Socket提供的通道

ServerSocketChannel 针对TCP协议服务器端Socket提供的通道

获取FileChannel对象

通过FileInputStream ,FileOutputStream, RandomAccessFile。

常用的方法

read() : 将Channel中的数据读取到Buffer中

write() : 向Buffer中写入数据

map(): 将channel中的数据全部或者部分映射到Buffer中

inChannel.map(mode, position, size)

MappedByteBuffer mappBuffer = inChannel.map(MapMode.READ_ONLY, 0, srcFile.length());

public class NIODemo03 {
	public static void main(String[] args) throws IOException {
//		File srcFile = new File("nio.txt");
//		FileInputStream fis = new FileInputStream(srcFile);
//		FileOutputStream fos = new FileOutputStream(new File("nio4.txt"));
		
		// 获取Channel对象
//		FileChannel inChannel = fis.getChannel();
//		FileChannel outChannel = fos.getChannel();
		
		// 获取Buffer对象
//		ByteBuffer buffer = ByteBuffer.allocate(10);
		
		// 将inChannel中的数据读取到Buffer中
//		int len = inChannel.read(buffer);
//		System.out.println(len);
//		byte[] bys = buffer.array();
//		System.out.println(new String(bys, 0, len));
//		//	切换成读模式
//		buffer.flip();
//		len = inChannel.read(buffer);
//		System.out.println(len);
//		System.out.println(new String(buffer.array(), 0, len));
//		buffer.flip();
//		
//		len = inChannel.read(buffer);
//		System.out.println(len);
//		System.out.println(new String(buffer.array(), 0, len));
//		buffer.flip();
		
//		int len = 0;
//		while ((len = inChannel.read(buffer)) != -1) {
//			buffer.flip();
//			System.out.print(new String(buffer.array(), 0, len));
//		}
		
//		while ((inChannel.read(buffer)) != -1) {
//			buffer.flip(); // 为取出数据做好准备
//			outChannel.write(buffer);
//			buffer.clear();
//		}
		
//		3.Channel能够将指定的部分或者全部文件映射到内存中
//		这里会抛出java.nio.channels.NonWritableChannelException
//      这是因为FileInputStream和FileOutputStream只能单独支持读或者是写
//		如果需要把指定的部分或者全部文件映射到内存中则推荐用 RandomAccessFile
//		MappedByteBuffer mapBuffer = inChannel.map(MapMode.READ_WRITE, 0, srcFile.length());
//		byte[] array = mapBuffer.array();
//		System.out.println(new String(array));
        
        
        RandomAccessFile raf = new RandomAccessFile("nio.txt", "rw");
		FileChannel channel = raf.getChannel();
		
		MappedByteBuffer mappedByteBuffer = channel.map(MapMode.READ_ONLY, 0, raf.length());
		
		channel.position(raf.length()); 
		
		channel.write(mappedByteBuffer);
        
	}
}
Charset
ublic class NIODemo05 {
	public static void main(String[] args) throws UnsupportedEncodingException, CharacterCodingException {
		String s = "Hello中国";
		// 编码
		byte[] bys = s.getBytes("utf-8");
		// [72, 101, 108, 108, 111, -42, -48, -71, -6]
		// [72, 101, 108, 108, 111, -28, -72, -83, -27, -101, -67]
		System.out.println(Arrays.toString(bys));
		
		// 解码
		// Hello涓浗    编码和解码用的不是同一个字符集那么就可能出现乱码现象
		String data = new String(bys, "gbk");
		System.out.println(data);
		
//		Charset defaultCharset = Charset.defaultCharset();
//		System.out.println(defaultCharset);
		// 获取当前JDK所支持的所有编码类型
//		SortedMap<String, Charset> map = Charset.availableCharsets();
//		Set<String> keys = map.keySet();
//		for (String key : keys) {
//			System.out.println(key + "=" + map.get(key));
//		}
		
//		Charset gbk = Charset.forName("gbk");
//		System.out.println(gbk);
//		
//		boolean supported = Charset.isSupported("ABC");
//		System.out.println(supported);
		
//		
//		1.创建编码表对象
		Charset utf8 = Charset.forName("utf-8");
		Charset gbk = Charset.forName("gbk");
		/*
		 * 2.创建编码器对象或者解码器对象
		 */
		CharsetEncoder utf8Encoder = utf8.newEncoder();
		CharsetDecoder utf8Decoder = utf8.newDecoder();
		
		CharsetEncoder gbkEncoder = gbk.newEncoder();
		CharsetDecoder gbkDecoder = gbk.newDecoder();
		
		// 3.创建需要编码或者解码的数据源,数据源一定要是Buffer
		CharBuffer charBuffer = CharBuffer.allocate(10);
		charBuffer.put("Hello中国");
		charBuffer.flip();
		System.out.println("======编码========");
		ByteBuffer byteBuffer = utf8Encoder.encode(charBuffer);
		
		for (int i = 0; i < byteBuffer.limit(); i++) {
			System.out.println(byteBuffer.get(i));
		}
		
		System.out.println("======解码========");
		CharBuffer charBuffer2 = gbkDecoder.decode(byteBuffer);
		System.out.println(charBuffer2);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值