基本数据类型流
数据输入流: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.如果启动了自动刷新,能够自动刷新。(启用了自动刷新,只有在调用println
、printf
或format
的其中一个方法时才可能完成自动刷新操作)
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);
}
}