java-day47-48
文章目录
- java-day47-48
- IO
- 1.流的概念
- 2.流的分类
- 3.字节流中的常用节点流
- 1)InputStream
- 例1:每次读取单个字节
- 例2:每次读取多个字节
- 例3:读取指定位置字节
- 例4:通过循环一次读取全部字节
- 例5:available()、markSupported()、mark 和 reset 方法
- 2)OutputStream
- 例6:结合InputStream和OutputStream
- 3)InputStream的子类和OutputStream的子类
- 4)System.out和System.in
- 5)ByteArrayInputStream和ByteArrayOutputStream
- 6)FileInputStream和FileOutputStream
- 7)PipedInputStream和PipedOutputStream
- 8)ObjectInputStream和ObjectOutputStream
- 9)java.io.File类
- 4.字节流中的常用处理流
- 5.字符流
- 6.转换流
- 7.对象流
- 8.随机访问流
IO
1.流的概念
流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以"流"的方式进行。设备可以是文件,网络,内存等
流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序为参考,如果数据的流向是程序至设备,我们成为输出流,如果数据的流向是设备至程序称为输入流。
数据以二进制的形式在程序与设备之间流动传输,就想水在管道里流动一样,所以就把这种数据传输的方式称之为输入流输出流
思考:代码程序中要读取文件中的内容,需要使用什么流?代码程序中要向文件中写内容,又需要使用什么流?
2.流的分类
1)按照流的方向分为输入流和输出流
2)按照处理数据的单位不同分为字节流和字符流
字节流读取的最小单位是一个字节(1byte=8bit),而字符流一次可以读取一个字符(1char = 2byte = 16bit)
3)按照功能的不同分为节点流和处理流
节点流是可以"直接"从一个数据源中读写数据的流。
处理流也可以称为功能流或者包装流,它是可以对节点流进行封装的一种流,封装后可以增加节点流的功能。
例如:FileInputStream是一个节点流,可以直接从文件读取数据,而BufferedInputStream可以包装 FileInputStream,使得其有缓冲数据的功能。
4)除了以上三种分类外,还有其他的一些类型的:对象流、缓冲流、压缩流、文件流等等,其实这些都是节点流或者处理流的子分类。当然还可以分出来其他的流类型,如果有这样需要的话。
5)不管流的分类是多么的丰富和复杂,其根源来自于四个基本的父类
字节输入流:InputStream
字节输出流:OutputStream
字符输入流:Reader
字符输出流:Writer
注:这四个父类都是抽象类
3.字节流中的常用节点流
注:java中常用的io流都在java.io包中
1)InputStream
//从输入流中读取数据的下一个字节
//如果到达流的末尾则返回 -1
public abstract int read();
//把读到的字节存到字节数组b中,并返回本次读到了多少个字节
public int read(byte[] b){..}
//把读到的字节存到字节数组b中,同时指定开始存的位置以及最大字节数,并返回本次读到了多少个字节
public int read(byte[] b,int off,int len){..}
//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
public int available(){..}
//跳过此输入流中数据的 n 个字节
public long skip(long n){..}
//关闭此输入流并释放与该流关联的所有系统资源
public void close(){..}
//测试此输入流是否支持 mark 和 reset 方法
public boolean markSupported(){..}
//在此输入流中标记当前的位置
public void mark(int readlimit){..}
//将此流重新定位到最后一次对此输入流调用mark方法时的位置
public void reset(){..}
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);//0-255
}
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
public long skip(long n) throws IOException {
long remaining = n;
int nr;
if (n <= 0) {
return 0;
}
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
byte[] skipBuffer = new byte[size];
while (remaining > 0) {
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
例1:每次读取单个字节
public class InputStreamTest {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//3、使用流
try {
int data = in.read();
System.out.println("data="+data);
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
例2:每次读取多个字节
public class InputStreamTest2 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//3、使用流
try {
//返回读到的字节数,数据放在数组里面
//一次最多读b.length个字节数,因为再多一个字节,数组就放不下了
byte[] b = new byte[5];
int len = in.read(b);
System.out.println("本次读取到"+len+"个字节:"+Arrays.toString(b));
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class InputStreamTest2 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//3、使用流
try {
//返回读到的字节数,数据放在数组里面
byte[] b = new byte[5];
int len = in.read(b);
System.out.println("本次读取到"+len+"个字节:"+Arrays.toString(b));
len = in.read(b);
System.out.println("本次读取到"+len+"个字节:"+Arrays.toString(b));
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
例3:读取指定位置字节
public class InputStreamTest3 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//3、使用流
try {
byte[] b = new byte[5];
//返回值表示本次共读到了多少个字节
//参数1 read方法读的字节存放到这个数组中
//参数2指定从数组中哪一个下标开始存数据
//参数3在数组中最多一次连续存多少个字节
int len = in.read(b,1,2);
System.out.println("len="+len+" "+Arrays.toString(b));
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
例4:通过循环一次读取全部字节
public class InputStreamTest4 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//3、使用流
try {
// int data = -1;
// while((data=in.read()) != -1) {
// System.out.println("data="+data);
// }
byte[] b = new byte[10];
int len = -1;
final byte[] BYE = {98, 121, 101, 13, 10};
while( (len=in.read(b)) != -1 ) {
System.out.println("读"+len+"个字节: "+Arrays.toString(b));
//前提要求数组b的长度大于等于BYE.length即可
if(len==5 && Arrays.equals(Arrays.copyOf(b, BYE.length), BYE)) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
例5:available()、markSupported()、mark 和 reset 方法
public class InputStreamTest5 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
in = System.in;//从控制台读数据
//System.out.println(in.getClass());
//实际类型 java.io.BufferedInputStream
//3、使用流
try {
//返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数
System.out.println("in.available():"+in.available());
//可以在读数据之前,先跳过指定的字节数
//in.available()的方法值,就是这个方法可以跳过的最大字节数
//System.out.println(in.skip(10));
//测试此输入流是否支持 mark 和 reset 方法
System.out.println("in.markSupported():"+in.markSupported());
int data = -1;
//hello
//104 101 108 108 111
while((data=in.read())!=-1) {
if(data==104) {
//在此输入流中标记当前的位置
in.mark(5);
}
else if(data==111) {
//将此流重新定位到最后一次对此输入流调用mark方法时的位置
in.reset();
}
System.out.println("data="+data);
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
if(in!=null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2)OutputStream
//将指定的字节写入此输出流
public abstract void write(int b);
//将字节数组b中的所有字节写入此输出流
public void write(byte[] b){..}
//将字节数组b中的字节写入此输出流,指定开始位置及最大字节数
public void write(byte[] b,int off,int len){..}
//刷新此输出流并强制写出所有缓冲的输出字节
public void flush(){..}
//关闭此输出流并释放与此流有关的所有系统资源
public void close(){..}
例6:结合InputStream和OutputStream
public class OutputStreamTest2 {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
OutputStream out = null;
//2、创建流
in = System.in;
out = System.out;
//3、使用流
try {
byte[] b = new byte[5];
int len = -1;
while((len=in.read(b))!=-1) {
out.write(b,0,len);//读出几个字节写几个字节
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
try {
if(out!=null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(in!=null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3)InputStream的子类和OutputStream的子类
几乎都是成对出现的,一个负责读数据的工作,一个负责写数据的工作
4)System.out和System.in
System类的部分源码:
public final class System{
//标准输入流
public final static InputStream in = null;
//标准输出流。
public final static PrintStream out = null;
//标准错误输出流
public final static PrintStream err = null;
public static void setIn(InputStream in){..}
public static void setOut(PrintStream out){..}
public static void setErr(PrintStream err){..}
}
标准输入流会默认从控制台读取数据
标准输出流会默认把数据输出到控制台
System.out.println(System.in.getClass());
System.out.println(System.out.getClass());
输出结果为:
class java.io.BufferedInputStream
class java.io.PrintStream
5)ByteArrayInputStream和ByteArrayOutputStream
ByteArrayInputStream可以从数组中读取字节
ByteArrayOutputStream可以把字节写到对象中的缓冲区里面,其实就是一个字节数组
public class ByteArrayInputStreamTest {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
//2、创建流
//把字符串变成字符数组
byte[] buf = "hello world".getBytes();
in = new ByteArrayInputStream(buf);
//3、使用流
try {
System.out.println("in.available():"+in.available());
//in.skip(in.available());全部被跳过
System.out.println("in.markSupported():"+in.markSupported());
int data = -1;
while((data=in.read())!=-1) {
if(data=='e') {
in.mark(1);//标记 参数没有用
}
else if(data == ' '){
in.reset();
}
//输出字节
System.out.write(data);
//将缓冲区数据刷新到控制台
System.out.flush();
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
try {
if(in!=null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class ByteArrayOutputStreamTest {
public static void main(String[] args) {
//1、声明流
OutputStream out = null;
//2、创建流
//把字符串变成字符数组
out = new ByteArrayOutputStream();
//3、使用流
try {
//把数据写到ByteArrayoutputStream对象中的buf属性中,buf是字节数组
byte[] b = "abc".getBytes();
out.write(b);
out.flush();
byte[] result = ((ByteArrayOutputStream)out).toByteArray();
System.out.println(Arrays.toString(result));
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
try {
if(out!=null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
6)FileInputStream和FileOutputStream
FileInputStream可以读取文件中的字节
FileOutputStream可以向文件中写进去字节
public class FileInputStreamTest {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
try {
//2、创建流
String fileName = "src/com/zzb/day47/test.txt";
in = new FileInputStream(fileName);
//3、使用流
byte [] b = new byte[10];
int len = -1;
long first = System.currentTimeMillis();
while((len=in.read(b)) != -1) {
System.out.write(b,0,len);
}
System.out.flush();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-first)+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
try {
if(in!=null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class FileOutputStreamTest {
public static void main(String[] args) {
//1、声明流
InputStream in = null;
OutputStream out = null;
try {
//2、创建流
String readFileName = "src/com/zzb/day47/test1.txt";
in = new FileInputStream(readFileName);
String writeFileName = "src/com/zzb/day47/test2.txt";
//构造器第二个参数,false表示内容覆盖,true表示内容追加
//如果使用的一参构造器,那么默认就是覆盖
out = new FileOutputStream(writeFileName,true);
//3、使用流
byte [] b = new byte[10];
int len = -1;
long first = System.currentTimeMillis();
while((len=in.read(b)) != -1) {
out.write(b,0,len);
}
out.flush();
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-first)+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}finally {
//4、关闭流
try {
if(in!=null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if(out!=null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
7)PipedInputStream和PipedOutputStream
PipedInputStream管道字节输入流
PipedOutputStream管道字节输出流
注:使用时需要把俩个管道进行对接
public class PipedStreamTest {
public static void main(String[] args) {
PipedInputStream in;
PipedOutputStream out;
try {
in = new PipedInputStream();
//让管道进行对接
out = new PipedOutputStream(in);
//把in和out分别交给俩个线程t1 t2,让线程操作管道流进行数据的传输
Thread t1 = new MyThread1(out);
Thread t2 = new MyThread2(in);
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
//复杂往管道中写数据
private static class MyThread1 extends Thread{
private PipedOutputStream out;
public MyThread1(PipedOutputStream out) {
this.out = out;
}
@Override
public void run() {
int data = -1;
try {
for(;;) {
data = (int)(Math.random()*26)+97;
out.write(data);
out.flush();
Thread.sleep(1000);
if(data == 'x') {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//负责从管道中读写数据
private static class MyThread2 extends Thread{
private PipedInputStream in;
public MyThread2(PipedInputStream in) {
this.in = in;
}
@Override
public void run() {
int data = -1;
try {
while((data=in.read()) != -1) {
System.out.write(data);
System.out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
8)ObjectInputStream和ObjectOutputStream
在序列化中要使用的对象输入流和对象输出流,之后再来使用测试
9)java.io.File类
File类型对象可以表示一个文件也可以表示一个目录.
package com.zzb.day48;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
public class FileTest {
public static void main(String[] args) {
FileTest t = new FileTest();
t.test1();
}
public void test1() {
File file = null;
// String pathName = "src/com/zzb/day48";
String pathName = "src/com/zzb/day48/test.txt";
file = new File(pathName);
System.out.println("是否存在:\t"+file.exists());//该file表示的文件或者文件夹存不存在
System.out.println("是否是文件夹:\t"+file.isDirectory());//判断file表示的是不是文件夹
System.out.println("是否是文件:\t"+file.isFile());//判断file表示的是不是文件
System.out.println("是否可读:\t"+file.canRead());
System.out.println("是否可写:\t"+file.canWrite());
System.out.println("是否可执行:\t"+file.canExecute());
System.out.println("文件名字:\t"+file.getName());
System.out.println("文件路径:\t"+file.getPath());
System.out.println("文件绝对路径:\t"+file.getAbsolutePath());
System.out.println("----------------------------------------");
// String parentName = file.getParent();
// System.out.println(parentName);
//获取file的父目录
File parentFile = file.getParentFile();
System.out.println("file的父目录为:\t"+parentFile.getPath());
//返回这个父目录中所有的文件或子目录
File[] listFiles = parentFile.listFiles();
for(File f:listFiles) {
System.out.println(f.getName());
}
System.out.println("-----------------------------------------");
listFiles = parentFile.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
return file.isFile() && file.canRead();
}
});
for(File f:listFiles) {
System.out.println(f.getName());
}
}
public void test2() {
File file = null;
String pathName = "src/com/zzb/day48/test1.txt";
try {
file = new File(pathName);
if(file.exists() == false) {
System.out.println("创建文件是否成功:\t"+file.createNewFile());
}
if(file.exists() == true && file.length()==0) {
file.delete();
// file.deleteOnExit();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void test3() {
File file = null;
String pathName = "src/com/zzb/day48/";
try {
// for(int i=1;i<=10;i++) {
// pathName = "src/com/briup/day48/test"+i+".txt";
// file = new File(pathName);
// if(file.exists() == false) {
// file.createNewFile();
// }
// }
file = new File(pathName);
if(file.exists() && file.isDirectory()) {
File[] list = file.listFiles(new FileFilter() {
@Override
public boolean accept(File f) {
return f.isFile() && f.getName().endsWith("txt") && f.length()==0;
}
});
for(File f:list) {
f.delete();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void test4() {
File file = null;
String pathName = "src/com/zzb/day48/test";
try {
file = new File(pathName);
if(file.exists() == false) {
file.mkdir();
}
if(file.exists() == true) {
file.delete();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.字节流中的常用处理流
也可以称为功能流或者包装流,因为它是对节点流进行包装的一种流,包装后可以增加节点流的功能。但是处理流本身并不能直接读写数据
1)BufferedInputStream和BufferedOutputStream
可以给字节流中的节点流提供代码缓冲区的输入/输出流
package com.zzb.day48;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class BufferedInputStreamTest {
@SuppressWarnings("unused")
public static void main(String[] args) {
InputStream in = null;
try {
String filePath = "src/com/zzb/day48/io.txt";
in = new FileInputStream(filePath );
//in = new BufferedInputStream(new FileInputStream(filePath));
long start = System.currentTimeMillis();
//int data = -1;
byte[] b = new byte[1024];
int len = -1;
while((len=in.read(b))!=-1) {
//
}
long end = System.currentTimeMillis();
System.out.println("共耗时"+(end-start)+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.zzb.day48;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class BufferedOutputStreamTest {
public static void main(String[] args) {
OutputStream out = null;
try {
String filePath = "src/com/zzb/day48/test.txt";
out = new BufferedOutputStream(new FileOutputStream(filePath));
// out = new FileOutputStream(filePath);
byte[] b = "hello world\n".getBytes();
long start = System.currentTimeMillis();
for(int i=0;i<10000;i++) {
out.write(b );
}
out.flush();
long end = System.currentTimeMillis();
System.out.println("共耗时"+(end-start)+"毫秒");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2)DataInputStream和DataOutputStream
可以给字节流中的节点流提供输入/输出java中不同类型的数据
public final void writeInt(int v) throws IOException {
out.write((v >>> 24) & 0xFF);
out.write((v >>> 16) & 0xFF);
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(4);
}
public final void writeShort(int v) throws IOException {
out.write((v >>> 8) & 0xFF);
out.write((v >>> 0) & 0xFF);
incCount(2);
}
public final void writeLong(long v) throws IOException {
writeBuffer[0] = (byte)(v >>> 56);
writeBuffer[1] = (byte)(v >>> 48);
writeBuffer[2] = (byte)(v >>> 40);
writeBuffer[3] = (byte)(v >>> 32);
writeBuffer[4] = (byte)(v >>> 24);
writeBuffer[5] = (byte)(v >>> 16);
writeBuffer[6] = (byte)(v >>> 8);
writeBuffer[7] = (byte)(v >>> 0);
out.write(writeBuffer, 0, 8);
incCount(8);
}
public final void writeBoolean(boolean v) throws IOException {
out.write(v ? 1 : 0);
incCount(1);
}
public final void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
public static int floatToIntBits(float value) {
int result = floatToRawIntBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & FloatConsts.EXP_BIT_MASK) ==
FloatConsts.EXP_BIT_MASK) &&
(result & FloatConsts.SIGNIF_BIT_MASK) != 0)
result = 0x7fc00000;
return result;
}
public final void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
public static long doubleToLongBits(double value) {
long result = doubleToRawLongBits(value);
// Check for NaN based on values of bit fields, maximum
// exponent and nonzero significand.
if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
DoubleConsts.EXP_BIT_MASK) &&
(result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
result = 0x7ff8000000000000L;
return result;
}
public class DataOutputStreamTest {
public static void main(String[] args) {
OutputStream out = null;
try {
String filePath="src/com/zzb/day48/test.txt";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
out = new DataOutputStream(bos);
((DataOutputStream)out).writeLong(1000L);
byte[] result= bos.toByteArray();
out.flush();
System.out.println(Arrays.toString(result));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.zzb.day48;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
@SuppressWarnings("unused")
public class DataOutputStreamTest {
public static void main(String[] args) {
OutputStream out = null;
try {
String filePath="src/com/zzb/day48/test.txt";
// out = new DataOutputStream(new FileOutputStream(filePath));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
out = new DataOutputStream(bos);
// ((DataOutputStream)out).writeLong(1000L);
((DataOutputStream)out).writeDouble(123.5D);
byte[] result= bos.toByteArray();
out.flush();
System.out.println(Arrays.toString(result));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
解释上面两个例子
public class Test {
public static void main(String[] args) {
String str = Long.toBinaryString(1000L);
System.out.println(str);
//00000000 00000000 00000000 00000000
//00000000 00000000 00000011 11101000
//1110100 -> 00010111 + 1 -> 00011000 -24
//{0,0,0,0,0,0,3,-24}
long a = Double.doubleToLongBits(123.5D);
//4638390956842811392
System.out.println(a);
//01000000 01011110 1110000 00000000
//00000000 00000000 0000000 00000000
//{64,94,-32,0,0,0,0,0}
System.out.println(Long.toBinaryString(a));
}
}
利用两个包装流进行读写
public class DataOutputStreamTest {
public static void main(String[] args) {
OutputStream out = null;
try {
String filePath="src/com/zzb/day48/test.txt";
out = new DataOutputStream(new FileOutputStream(filePath));
((DataOutputStream)out).writeInt(50529025);
((DataOutputStream)out).writeInt(1);
((DataOutputStream)out).writeLong(1000L);
((DataOutputStream)out).writeUTF("HELLO");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class DataInputStreamTest {
public static void main(String[] args) {
InputStream in = null;
try {
String filePath ="src/com/zzb/day48/test.txt";
in = new DataInputStream(new FileInputStream(filePath));
System.out.println(((DataInputStream)in).readInt());
System.out.println(((DataInputStream)in).readInt());
System.out.println(((DataInputStream)in).readLong());
System.out.println(((DataInputStream)in).readUTF());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
3)PrintStream
PrintStream为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
注意,这个包装类中的方法可以接受各种各种的类型的参数(重载),但是内部会把这些数据再变成相应的字符串,然后在进行输出。
public class PrintStreamTest {
public static void main(String[] args) {
PrintStream out = null;
ByteArrayOutputStream bos = null;
try {
bos = new ByteArrayOutputStream();
out = new PrintStream(bos);
out.println(1000L);
//1000 -> 字符串 1 0 0 0 回车 换行
out.flush();
byte[] buf =bos.toByteArray();
System.out.println(Arrays.toString(buf));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(bos!=null)
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
5.字符流
1)Reader
public int read(){..}
public int read(char[] cbuf){..}
public abstract int read(char[] cbuf, int off,int len){..}
//指定缓冲区
//@since 1.5
public int read(CharBuffer target){..}
abstract public void close();
public long skip(long n){..}
public boolean markSupported(){..}
public void mark(int readAheadLimit){..}
public void reset(){..}
//Tells whether this stream is ready to be read
public boolean ready(){..}
2)Writer
public void write(int c){..}
public void write(char cbuf[]){..}
abstract public void write(char cbuf[], int off, int len);
public void write(String str){..}
public void write(String str, int off, int len){..}
abstract public void flush();
abstract public void close();
//@since 1.5
//和out.write(c)的效果一样
public Writer append(char c){..}
public Writer append(CharSequence csq){..}
public Writer append(CharSequence csq, int start, int end){..}
3)CharArrayReader和CharArrayWriter
CharArrayReader可以读取字符数组中的内容
public class CharArrayReaderTest {
public static void main(String[] args) {
Reader in = null;
try {
char[] buf = "中国 hello".toCharArray();
in = new CharArrayReader(buf);
/*
int data = -1;
while((data=in.read())!=-1) {
//System.out.write(data);
System.out.flush();
}*/
int len = -1;
char[] cbuf = new char[5];
while((len=in.read(cbuf))!=-1) {
System.out.println(len+":"+Arrays.toString(cbuf));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
CharArrayWriter可以向字符数组中写内容
public class CharArrayWriterTest {
public static void main(String[] args) {
Writer out = null;
try {
out = new CharArrayWriter();
out.write("邹泽斌");
out.flush();
char [] buf =((CharArrayWriter)out).toCharArray();
System.out.println(Arrays.toString(buf));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
4)FileReader和FileWriter
FileReader读取文件内容的便捷类,InputStreamReader的子类
public class FileReaderTest {
public static void main(String[] args) {
Reader in = null;
try {
String fileName = "src/com/zzb/day49/io.txt";
in = new FileReader(fileName );
char[] cbuf = new char[1024];
int len = -1;
while((len=in.read(cbuf)) != -1) {
String str = new String(cbuf,0,len);
System.out.print(str);
}
System.out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
FileWriter写入文件内容的便捷类,OutputStreamWriter的子类
public class FileWriterTest {
public static void main(String[] args) {
Reader in = null;
Writer out = null;
try {
String readFileName = "src/com/zzb/day49/io.txt";
in = new FileReader(readFileName);
String writeFileName = "src/com/zzb/day49/test.txt";
out = new FileWriter(writeFileName);
char[] cbuf = new char[1024];
int len = -1;
while((len=in.read(cbuf)) != -1) {
out.write(cbuf, 0, len);
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5)PipedReader和PipedReader
PipedReader管道字符输入流
PipedReader管道字符输出流
public class PipedReaderTest {
public static void main(String[] args) {
PipedReader in = null;
PipedWriter out = null;
try {
in = new PipedReader();
out = new PipedWriter(in);
Thread t1 = new MyThread1(in);
Thread t2 = new MyThread2(out);
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
private static class MyThread1 extends Thread {
private PipedReader in;
public MyThread1(PipedReader in) {
this.in = in;
}
@Override
public void run() {
int data = -1;
try {
while((data=in.read())!=-1) {
System.out.write(data);
System.out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static class MyThread2 extends Thread {
private PipedWriter out;
public MyThread2(PipedWriter out) {
this.out = out;
}
@Override
public void run() {
try {
for(int i=0;i<256;i++) {
out.write(i);
out.flush();
if(i%20==0) {
System.out.print("\n---------分割--------\n");
}
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class PipedReaderTest2 {
public static void main(String[] args) {
PipedReader in = null;
PipedWriter out = null;
try {
in = new PipedReader();
out = new PipedWriter(in);
Thread t1 = new MyThread1(in);
Thread t2 = new MyThread2(out);
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
private static class MyThread1 extends Thread {
private PipedReader in;
public MyThread1(PipedReader in) {
this.in = in;
}
@Override
public void run() {
Writer out = null;
try {
String fileName = "src/com/zzb/day49/a.txt";
out = new FileWriter(fileName);
char[] cbuf = new char[128];
int len = -1;
while((len=in.read(cbuf)) != -1) {
out.write(cbuf, 0, len);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static class MyThread2 extends Thread {
private PipedWriter out;
public MyThread2(PipedWriter out) {
this.out = out;
}
@Override
public void run() {
Reader in = null;
try {
in = new InputStreamReader(System.in);
char[] cbuf = new char[128];
int len = -1;
while((len=in.read(cbuf)) != -1) {
out.write(cbuf, 0, len);
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
6)BufferedReader和BufferedWriter
这个俩个流属于处理流,它们本身并不能读取数据,它们的作用是包装在其他节点流上面,为其提供额外的功能
public class BufferedReaderTest2 {
public static void main(String[] args) {
BufferedReader in = null;
try {
String fileName = "src/com/zzb/day49/stu.txt";
in = new BufferedReader(new FileReader(fileName ));
String line = null;
List<Student> list = new ArrayList<>();
while((line=in.readLine()) != null) {
Student stu = stringToStudent(line);
if(stu==null) {
System.out.println("当前数据有问题,直接进入下次操作:"+line);
continue;
}
list.add(stu);
}
System.out.println("list.size() = "+list.size());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static Student stringToStudent(String line) {
//1:tom1:21
String[] arr = line.split(":");
if(arr.length != 3) {
return null;
}
long id = Long.valueOf(arr[0]);
String name = arr[1];
int age = Integer.valueOf(arr[2]);
return new Student(id,name,age);
}
}
public class BufferedWriterTest {
public static void main(String[] args) {
//window中默认是\r\n
//linux中默认是\n
// String str = System.getProperty("line.separator");
// System.out.println(Arrays.toString(str.getBytes()));
BufferedWriter out = null;
try {
String fileName = "src/com/zzb/day49/a.txt";
out = new BufferedWriter(new FileWriter(fileName ));
out.write("hello");
out.newLine();
out.write("world");
out.newLine();
out.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7)PrintWriter
一般会把BufferedReader和PrintWriter配合在一起使用,因为BufferedReader可以一次读一行字符串,而PrintWriter可以一次写一行字符串(自动换行)。
public class PrintWriterTest {
public static void main(String[] args) {
PrintWriter out = null;
try {
// String fileName = "src/com/zzb/day49/a.txt";
// out = new PrintWriter(new File(fileName ));
// out = new PrintWriter(System.out);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
out = new PrintWriter(bos);
out.println("hello1");
out.println("hello2");
out.println("hello3");
out.flush();
byte[] buf = bos.toByteArray();
System.out.println(Arrays.toString(buf));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class PrintWriterTest2 {
public static void main(String[] args) {
PrintWriter out = null;
try {
String fileName = "src/com/zzb/day49/stu.txt";
out = new PrintWriter(new File(fileName));
List<Student> list = getStudents();
//new Student(1L,"tom1",21) --> 1:tom1:21
for(Student stu:list) {
out.println(stu.toString());
}
out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static List<Student> getStudents(){
List<Student> list = new ArrayList<>();
list.add(new Student(1L,"tom1",21));
list.add(new Student(2L,"tom2",22));
list.add(new Student(3L,"tom3",23));
list.add(new Student(4L,"tom4",24));
list.add(new Student(5L,"tom5",25));
return list;
}
}
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private long id;
private String name;
private transient int age;
public Student() {
}
public Student(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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 [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
6.转换流
InputStreamReader和OutputStreamWriter是一对名字中既有Stream,又有Reader或Writer的流,因为它们是转换流,负责把一个字节流转换为字符流。所以它们是字节流和字符串之间的桥梁.
注:在把字节流转换为字符流的过程中,还可以指定字符编码,避免乱码的出现。
public class InputStreamReaderTest {
public static void main(String[] args) {
BufferedReader in = null;
try {
String fileName = "src/com/zzb/day49/a.txt";
// in = new InputStreamReader(new FileInputStream(fileName ));
String charsetName = "UTF-8";
// String charsetName = "GBK";
in = new BufferedReader(
new InputStreamReader(new FileInputStream(fileName),charsetName));
String line = null;
while((line=in.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public class OutputStreamWriterTest {
public static void main(String[] args) {
PrintWriter out = null;
try {
String fileName = "src/com/zzb/day49/a.txt";
String charsetName = "UTF-8";
// String charsetName = "GBK";
out = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(fileName),charsetName));
// out = new PrintWriter(fileName);
// out = new PrintWriter(new FileOutputStream(fileName));
out.println("你好,hello");
out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null)out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
7.对象流
1)序列化和反序列化
Java中的序列化是指把Java对象转换为字节序列的过程
对象—序列化—>01010101
Java中的反序列化是指把字节序列恢复为Java对象的过程
01010101—反序列化—>对象
思考:为什么需要序列化和反序列化?
2)如何实现序列化和反序列化
使用对象流即可实现对象的序列化和反序列化
ObjectOutputStream类中的方法可以完成对象的序列化:
public final void writeObject(Object obj){…}
public class ObjectOutputStreamTest {
public static void main(String[] args) {
ObjectOutputStream out = null;
try {
String fileName = "src/com/zzb/day49/obj.txt";
out = new ObjectOutputStream(new FileOutputStream(fileName ));
Student stu = new Student(1L,"tom1",21);
//对象的序列化
//对象--->字节
out.writeObject(stu);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null) out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
ObjectOutputStream out = null;
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
out = new ObjectOutputStream(bos);
List<Student> list = new ArrayList<>();
for(int i=1;i<=20;i++) {
list.add(new Student(i,"tom"+i,20+i));
}
out.writeObject(list);
out.flush();
byte[] buf = bos.toByteArray();
System.out.println(buf.length);
System.out.println(Arrays.toString(buf));
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null) out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ObjectInputStream类中的方法可以完成对象的反序列化:
public final Object readObject(){…}
public class ObjectInputStreamTest {
public static void main(String[] args) {
ObjectInputStream in = null;
try {
String fileName = "src/com/zzb/day49/obj.txt";
in = new ObjectInputStream(new FileInputStream(fileName ));
//对象的反序列化
//字节 --->对象
Object obj = in.readObject();
System.out.println(obj instanceof Student);
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null) in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注:这俩个对象流都属于字节流
3)序列化的要求
只有实现了java.io.Serializable接口的类的对象才可以被序列化,否则序列化时会报错
思考:测试序列化版本号的作用是什么?
4)transient关键字
在对象序列化的时候,被transient修饰的属性的值,在序列化过程中是会被忽略掉的。
8.随机访问流
java.io.RandomAccessFile类
public class RandomAccessFile extends Object{…}
这是个特殊的流,它不属于之前那些流的体系。
这个流的既可以用来读文件,也可以用来给文件中写内容,并且该类中的方法可以用来定位文件中的位置:
public native void seek(long pos);
构造器中需要设置该流的操作模式:
//对文件只读
RandomAccessFile r = new RandomAccessFile(filePath,"r");
//对文件即可读又可写
//但是一旦确定了读或者写,那么就不能在变
RandomAccessFile rw = new RandomAccessFile(filePath,"rw");
public class RandomAccessFileTest {
public static void main(String[] args) {
//针对文件的 随机访问流
//和之前的流不同之处在于,这种流不仅可以在读的时候进行随机定位,再写的时候也可以进行随机定位。
RandomAccessFile in = null;
RandomAccessFile out = null;
try {
File file = new File("src/com/zzb/day49/test.txt");
in = new RandomAccessFile(file, "r");
out = new RandomAccessFile("src/com/zzb/day49/testCopy.txt", "rw");
byte[] buf = new byte[128];
int len = -1;
long fileLength = file.length();
in.seek(fileLength/2);
out.seek(fileLength/2);
while((len=in.read(buf))!=-1) {
out.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(in!=null)in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(out!=null)out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}