Java 数据流 接口 DataInput 和 DataOutput,设计了一种较为高级的数据输入输出方式:除了可处理字节和字节数组外,还可以处理 int、float、boolean 等基本数据类型,这些数据在文件中的表示方式和它们在内存中的一样,无须转换,如 read(), readInt(), readByte()…; write(), writeChar(), writeBoolean()… 此外,还可以用 readLine() 方法读取一行信息。
常用方法
方法
返回值
说明
readBoolean()
boolean
readByte()
byte
readShort()
short
readChar()
char
readInt()
int
readLong()
long
readDouble()
double
readFloat()
float
readUnsignedByte()
int
readUnsignedShort()
int
readFully(byte[] b)
void
从输入流中读取一些字节,并将它们存储在缓冲区数组 b 中
reaFully(byte[] b, int off,int len)
void
从输入流中读取 len 个字节
skipBytes(int n)
int
与 InputStream.skip 等价
readUTF()
String
按照 UTF-8 形式从输入中读取字符串
readLine()
String
按回车 (\r) 换行 (\n) 为分割符读取一行字符串,不完全支持 UNICODE
writeBoolean(boolean v)
void
writeByte(int v)
void
writeShort(int v)
void
writeChar(int v)
void
writeInt(int v)
void
writeLong(long v)
void
writeFloat(float v)
void
writeDouble(double v)
void
write(byte[] b)
void
与 OutputStream.write 同义
write(byte[] b, int off, int len)
void
与 OutputStream.write 同义
write(int b)
void
与 OutputStream.write 同义
writeBytes(String s)
void
只输出每个字符的低 8 位;不完全支持 UNICODE
writeChars(String s)
void
每个字符在输出中都占两个字节
数据流类 DataInputStream 和 DataOutputStream 的处理对象除了是字节或字节数组外,还可以实现对文件的不同数据类型的读写:
分别实现了 DataInput 和 DataOutput 接口。
在提供字节流的读写手段同时,以统一的形式向输入流中写入 boolean,int,long,double 等基本数据类型,并可以再次把基本数据类型的值读取回来。
提供了字符串读写的手段。
数据流可以连接一个已经建立好的数据对象,例如网络连接、文件等。数据流可以通过如下方式建立:
1 2 3 4 FileInputStream fis = new FileInputStream("file1.txt"); FileOutputStream fos = new FileOutputStream("file2.txt"); DataInputStream dis = new DataInputStream(fis); DataOutputStream dos = new DataOutputStream(fos);
新建源代码文件 DataStream.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class DataStream { public static void main(String[] args) throws IOException{ //向文件 a.txt 写入 FileOutputStream fos = new FileOutputStream("a.txt"); DataOutputStream dos = new DataOutputStream(fos); try { dos.writeBoolean(true); dos.writeByte((byte)123); dos.writeChar('J'); dos.writeDouble(3.1415926); dos.writeFloat(2.122f); dos.writeInt(123); } finally { dos.close(); } //从文件 a.txt 读出 FileInputStream fis = new FileInputStream("a.txt"); DataInputStream dis = new DataInputStream(fis); try { System.out.println("\t" + dis.readBoolean()); System.out.println("\t" + dis.readByte()); System.out.println("\t" + dis.readChar()); System.out.println("\t" + dis.readDouble()); System.out.println("\t" + dis.readFloat()); System.out.println("\t" + dis.readInt()); } finally { dis.close(); } } }
编译运行:
1 2 3 4 5 6 7 8 $ javac DataStream.java $ java DataStream true 123 J 3.1415926 2.122 123
读写对象 我们知道实例化的对象存在于内存中,如果我们想传输实例化的对象怎么办呢?可以通过 ObjectOutputStream 和 ObjectInputStream 将对象输入输出。 将对象的状态信息转换为可以存储或者传输的形式的过程又叫序列化。
新建一个源代码文件 ReadWriteObject.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import java.io.*; public class ReadWriteObject { public static void main(String[] args) { File file = new File("/home/project/user.file"); try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file))) { //将匿名对象 写入到file中,注意:被写入的对象必须实现了Serializable接口 objectOutputStream.writeObject(new User("admin", "adminpwd")); objectOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } //读取文件 打开输入流 try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file))) { // 将信息还原为user实例 User user = (User) objectInputStream.readObject(); //打印user信息 和上面创建的匿名对象的信息一致 System.out.println(user.toString()); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } //静态内部类 必须实现Serializable static class User implements Serializable { private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; } @Override public String toString() { return "User{" + "username='" + username + '\'' + ", password='" + password + '\'' + '}'; } } }
编译运行:
1 2 3 $ javac ReadWriteObject.java $ java ReadWriteObject User{username='admin', password='adminpwd'}
NIO Java NIO(New IO) 发布于 JDK1.4,用于代替 Java 标准 IO 。Java NIO 是面向缓存的、非阻塞的 IO,而标准 IO 是面向流的,阻塞的 IO。
首先理解 NIO 的重要概念:Buffer(缓冲区)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.util.Scanner; public class NioDemo { public static void main(String[] args) { try { File file = new File("/home/project/nio.txt"); if (!file.exists()) { file.createNewFile(); } //创建channel nio通过channel来连接文件 相当于桥梁 FileChannel writeChannel = new RandomAccessFile(file, "rw").getChannel(); //创建一个ByteBuffer 容量为100 ByteBuffer byteBuffer = ByteBuffer.allocate(100); System.out.println("请输入字符串"); Scanner in = new Scanner(System.in); String s = in.nextLine(); //将字符串写入到缓冲区 byteBuffer.put(s.getBytes()); System.out.println("写入数据后指针变化-position:" + byteBuffer.position() + " limit:" + byteBuffer.limit() + " capacity :" + byteBuffer.capacity()); //为输出数据做准备 将limit移动到position位置,position置0 byteBuffer.flip(); System.out.println("flip后指针变化-position:" + byteBuffer.position() + " limit:" + byteBuffer.limit() + " capacity :" + byteBuffer.capacity()); //将缓冲区写入channel writeChannel.write(byteBuffer); //清除缓冲区 为下次写入或者读取数据做准备 恢复到初始状态 position=0 limit=capacity=100 因为我们这里分配的容量大小为100 byteBuffer.clear(); System.out.println("clear后指针变化-position:" + byteBuffer.position() + " limit:" + byteBuffer.limit() + " capacity :" + byteBuffer.capacity()); //关闭channel writeChannel.close(); FileChannel readChannel = new RandomAccessFile(file, "r").getChannel(); //从channel中将数据读取到缓冲区 while (readChannel.read(byteBuffer) != -1) { //为读取数据做准备 byteBuffer.flip(); //输出数据 设置解码器 Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); System.out.println("读取结果:" + decoder.decode(byteBuffer)); //清除缓冲区 byteBuffer.clear(); } readChannel.close(); } catch (IOException e) { e.printStackTrace(); } } }
运行示例:
1 2 3 4 5 6 7 8 $ javac NioDemo.java $ java NioDemo 请输入字符串 hellojava 写入数据后指针变化-position:9 limit:100 capacity :100 flip后指针变化-position:0 limit:9 capacity :100 clear后指针变化-position:0 limit:100 capacity :100 shiyanlou