一、字节数组流
字节数组流类能够操作内存中的字节数组,它的数据是一个字节数组。字节数组流类本身适配器设计模式,它把字节数组类型转为流类型使得程序能够对字节数组进行读写操作。
1.ByteArrayInputStream类
类从内存中的字节数组读入数据,它的数据是一个字节数组。ByteArrayInputStream流类本身适配器设计模式,它把字节数组类型转换为输入流类型使得程序能够对字节数组进行读操作。
下面是示例代码:
public class ByteArrayInputStreamDemo {
public static void main(String args[]) throws IOException{
readByteArrayStream();
}
/***
* ByteArrayInputStream读取字节数组的方法
* @throws IOException
*/
public static void readByteArrayStream() throws IOException{
String str="zhisytoitheima";
byte[] strBuf=str.getBytes();
ByteArrayInputStream baiS=new ByteArrayInputStream(strBuf);
int data=baiS.read();
while(data!=-1){
char upper=Character.toUpperCase((char)data);
System.out.print(upper+" ");
data=baiS.read();
}
baiS.close();
}
}
运行结果如下:
2.ByteArrayOutputStream类
类向内存中的字节数组写入数据,它的数据是一个字节数组。ByteArrayOutputStream流类本身适配器设计模式,它把字节数组类型转换为输出流类型使得程序能够对字节数组进行写操作。
类的构造方法如下:
ByteArrayOutputStream():创建一个新的字节数组输出流,缓冲区的初始是32个字节,如有必要可增加大小。
ByteArrayOutputStream(int size):创建一个新的字节数组输出流,它具有指定大小的缓冲区容量,容量以字节为单位。
代码示例:
1 /**
2 * 把字符串转换为字节数组再写到字节数组输出流中
3 * @author 支胜勇
4 *
5 */
6 public class ByteArrayOutputStreamDemo {
7
8 public static void main(String args[]) throws IOException{
9
10 writeByteArrayStream();
11 }
12
13
14 /***
15 * ByteArrayInputStream读取字节数组的方法
16 * @throws IOException
17 */
18 public static void writeByteArrayStream() throws IOException{
19
20 String str="zhisytoitheimatestByteArrayInputStream";
21 byte[] strBuf=str.getBytes();
22 ByteArrayOutputStream baoS=new ByteArrayOutputStream(512);
23
24 baoS.write(strBuf);//将指定的字节数组中的字节写入baoS字节数组输出流中
25 System.out.println(baoS.toString().toUpperCase());//通过解码字节将缓冲区内容转换为字符串输出
26
27 //创建一个行新分配的字节数组,并将字节数组输出流中的内容复制到该数组中
28 byte[] newStrBuf=baoS.toByteArray();
29 for(int i=0;i<newStrBuf.length;i++){
30 System.out.print((char)newStrBuf[i]);
31 }
32
33 }
34 }
二、管道流
PipedInputStream对象必须和一个PipedOutputStream对象进行连接从而产生一个通信管道。PipedOutputStream可以向管道中写入数据,通常一个线程向管道输出流写入数据,另一个线程从管道输入流中读取数据,PipedInputStream可以从管道中读取PipedOutputStream写入的数据。这两个类主要用来完成线程之间的通信。当线程A执行管道输入流的read()方法时,如果暂时还没有数据,则这个线程就会被阻塞,只有当线程B向管道输出流谢了新的数据后,线程A才会被回复运行。
示例代码:
1 /**
2 * 向管道输输出流写入数据的线程
3 */
4 class MyWriter extends Thread{
5
6 private PipedOutputStream out=new PipedOutputStream();
7 private String content="";
8
9 public MyWriter(String content){
10
11 this.content=content;
12 }
13
14
15 public PipedOutputStream getOut() {
16 return out;
17 }
18
19 @Override
20 public void run() {
21 // TODO Auto-generated method stub
22 super.run();
23 try{
24 System.out.println("--------我开始向管道写入数据------");
25 out.write(content.getBytes());
26 out.close();
27 System.out.println("--------向管道写入数据结束------");
28 }catch(Exception e){
29
30 throw new RuntimeException(e);
31 }
32 }
33
34 }
35
36
37 /***
38 * 向管道输入流中读取数据
39 */
40 public class PipedStreamDemo extends Thread{
41
42 private PipedInputStream in;
43
44 public PipedStreamDemo(MyWriter out) throws IOException{
45
46 this.in=new PipedInputStream();
47 in.connect(out.getOut());//连接管道输出流和管道输入流
48 }
49
50
51 @Override
52 public void run() {
53 // TODO Auto-generated method stub
54 super.run();
55
56 try{
57 byte[] buf=new byte[1024];
58 int len=0;
59 String readStr="";
60 System.out.println("-------我在等待向管道写入数据!--------");
61 while((len=in.read(buf))!=-1){
62
63 readStr+=new String(buf,0,len);
64 }
65 System.out.println(readStr);
66 in.close();
67 System.out.println("-------我从管道读取数据结束!--------");
68 }catch(Exception e){
69
70 throw new RuntimeException(e);
71 }
72 }
73
74
75 public static void main(String args[]) throws IOException{
76
77 MyWriter myW=new MyWriter("我很想到黑马去!");
78
79 PipedStreamDemo myR=new PipedStreamDemo(myW);
80 myW.start();
81 myR.start();
82 }
83
84 }
三、随机访问文件类
Java中,RandomAccessFile类的一个对象提供了对随机读/写文件的支持,它没有继承InputStream和OutputStream,而是直接继承了Object,并且实现了接口DataInput和DataOutput。在生成一个RandomAccessFile对象时,除了要指明文件对象或文件名外,还需要指明读/写模式。例如下面的语句:
RandomAccessFile raf=new RandomAccessFile(“E:\\yy.dat”,”r”);表示对文件E:\\yy.dat进行随机读操作
RandomAccessFile raf=new RandomAccessFile(“E:\\yy1.dat”,”rw”);表示对文件E:\\yy1.dat进行随机读/写操作
Java随机读/写的字节文件看成是一个很大的字节数组,随机读/写操作可看成是对这个“虚拟的字节数组”进行的,这个“数组”的下标就是所谓的文件指针,因此随机读/写文件的首要操作就是移动文件的指针,其操作有以下三个:
long getFilePointer():当前文件的指针位置。
void seek(long pos):移动文件指针到指定的位置,从0开始计算位置。
int skipBytes(int n):将文件指针向文件末尾移动指定的n个字节,返回实际移动的字节数,若n<0则不发生移动。
示例代码:
1 /**
2 * 向e:\\yy.txt文件写入10个double型的实数,然后运用RandomAccessFile随机修改其中的数据
3 * @author 支胜勇
4 *
5 */
6 public class RandomRWDemo {
7
8
9 public static void main(String[] args) throws IOException{
10
11 randomWrite("E:\\yy.dat");
12
13 randomModify("E:\\yy.dat");
14 }
15
16
17 /***
18 * 向文件写入数据
19 * @param fileName
20 * @throws IOException
21 */
22 public static void randomWrite(String fileName) throws IOException{
23
24 File file=new File(fileName);
25 if(!file.exists()){
26
27 file.createNewFile();
28 }
29
30 if(!file.isFile()){//如果不是文件则返回
31
32 System.out.print("不是文件");
33 return;
34 }
35
36
37
38 RandomAccessFile aWFile=new RandomAccessFile(file,"rw");
39 int i=1;
40 while(i<=10){
41 aWFile.writeDouble(i);//写入doubl值
42 System.out.print(" "+(double)i);
43 i++;
44 }
45 aWFile.close();
46 }
47
48
49 public static void randomModify(String fileName) throws IOException{
50
51 final int DOUBLE_SIZE=8;//double类型占8个字节
52 File file=new File(fileName);
53 if(!file.exists()){
54 System.out.println("要修改的文件不存在");
55 return;
56 }
57
58 if(!file.isFile()){
59 System.out.println("不是文件");
60 return;
61 }
62
63 RandomAccessFile aMFile=new RandomAccessFile(file,"rw");
64
65 aMFile.seek(2*DOUBLE_SIZE);//修改第2个double值
66 aMFile.writeDouble(100);
67
68 aMFile.seek(7*DOUBLE_SIZE);//修改第7个double值
69 aMFile.writeDouble(200);
70
71 aMFile.close();
72
73 //查看是否已修改
74
75 RandomAccessFile aRFile=new RandomAccessFile(file,"r");
76 System.out.println();
77 for(int i=0;i<10;i++){
78 System.out.print(" "+aRFile.readDouble());
79 }
80 aRFile.close();
81 }
82
83 }
运行结果: