疯狂的小鸡

IO-java.io

字数统计: 1.5k阅读时长: 6 min
2018/10/12 Share

IO关注两类对象,一类是数据对象,一类是IO流对象。

数据对象关注数据从哪读,往哪写。对应data source 与 data destination

IO流对象是是一系列流动数据,流对象链接这数据对象。
IO流
IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,Java对于数据的操作都是通过流实现,而java用于操作流的对象都在IO包中。

分类

按操作数据分为:字节流和字符流。 如:Reader和InpurStream
按流向分:输入流和输出流。如:InputStream和OutputStream

IO流常用的基类:
InputStream , OutputStream

字符流的抽象基类:
Reader , Writer

由上面四个类派生的子类名称都是以其父类名作为子类的后缀:
如:FileReader和FileInputStream

字符流

字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码。
字符流只用来处理文本数据,字节流用来处理媒体数据。

数据最常见的表现方式是文件,字符流用于操作文件的子类一般是FileReader和FileWriter。

字符流读写:

注意事项:

  • 写入文件后必须要用flush()刷新。

  • 用完流后记得要关闭流。

  • 使用流对象要抛出IO异常。

  • 定义文件路径时,可以用“/”或者“\”。

  • 在创建一个文件时,如果目录下有同名文件将被覆盖。

  • 在读取文件时,必须保证该文件已存在,否则出异常。

文件写出一例

1
2
3
4
5
6
7
8
9
10
11
12
13
FileWriter fw = new FileWriter("F:\\1.txt");//目的是明确数据要存放的目的地。  
 
//调用write的方法将字符串写到流中  
fw.write("hello world!");  
      
//刷新流对象缓冲中的数据,将数据刷到目的地中  
fw.flush();  

//没有flush的数据还在缓存中,不会被立即看到
fw.write("first_test");  

//关闭流资源 close()方法中会首先执行一次flush(); 
fw.close();

文件读入一例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FileReader fr = new FileReader("Demo.txt");  

char []  buf = new char[6];   

//将Denmo中的文件读取到buf数组中。  
int num = 0;      
while((num = fr.read(buf))!=-1) {  
  
//String(char[] value , int offest,int count) 
//分配一个新的String,包含从offest开始的count个字符  
System.out.println(new String(buf,0,num));  
}  

System.out.println('\n');  
fr.close();

指定编码

1
new FileOutputStream("goods1.txt"),"UTF-8")

字符流的缓冲区:BufferedReader和BufferedWreiter

缓冲区的出现时为了提高流的操作效率而出现的。将需要被提高效率的流作为参数传递给缓冲区的构造函数。在缓冲区中封装了一个数组,存入数据后一次取出。

BufferedReader示例

1
2
3
4
5
6
7
8
9
10
11
12
FileReader rw = new FileReader("buf.txt");  
  
//只要将需要被提高效率的流作为参数传递给缓冲区的构造函数即可  
BufferedReader brw = new BufferedReader(rw);  
          
for(;;) {  
      String s = brw.readLine();  
      if(s==nullbreak;  
      System.out.println(s);  
}  
          
brw.close();//关闭输入流对象

读取流缓冲区提供了一个一次读一行的方法readline,方便对文本数据的获取。

readline()只返回回车符前面的字符,不返回回车符。如果是复制的话,必须加入newLine(),写入回车符。newLine()是java提供的多平台换行符写入方法。

BufferedWriter示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//创建一个字符写入流对象  
FileWriter fw = new FileWriter("buf.txt");  
  
//为了提高字符写入效率,加入了缓冲技术。  
//只要将需要被提高效率的流作为参数传递给缓冲区的构造函数即可  
BufferedWriter bfw = new BufferedWriter(fw);  

//bfw.write("abc\r\nde");  
//bfw.newLine();           这行代码等价于bfw.write("\r\n"),相当于一个跨平台的换行符  
//用到缓冲区就必须要刷新  
for(int x = 1; x < 5; x++) {  
      bfw.write("abc");  
      bfw.newLine();                  //java提供了一个跨平台的换行符newLine();  
      bfw.flush();  
}  
 
bfw.flush();                         //刷新缓冲区  
bfw.close();                         //关闭缓冲区,但是必须要先刷新  

//注意,关闭缓冲区就是在关闭缓冲中的流对象  
fw.close();

字节流

  • 字节流和字符流的基本操作是相同的,但是要想操作媒体流就需要用到字节流。

  • 字节流因为操作的是字节,所以可以用来操作媒体文件。(媒体文件也是以字节存储的)

  • 读写字节流:InputStream 输入流(读)和OutputStream 输出流(写)

  • 字节流操作可以不用刷新流操作。

  • InputStream特有方法:

    int available();//返回文件中的字节个数
    

    注:可以利用此方法来指定读取方式中传入数组的长度,从而省去循环判断。但是如果文件较大,而虚拟机启动分配的默认内存一般为64M。当文件过大时,此数组长度所占内存空间就会溢出。所以,此方法慎用,当文件不大时,可以使用。

文件复制示例

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
public static void copyBmp() {  

     FileInputStream fis = null;  
    FileOutputStream fos = null;  
    try {  
         fis = new FileInputStream("F:\\java_Demo\\day9_28\\1.bmp");            
        fos = new FileOutputStream("F:\\java_Demo\\day9_28\\2.bmp");           
         byte[] copy = new byte[1024];  
       int len = 0;  
         while((len=fis.read(copy))!=-1) {  
             fos.write(copy,0,len);  
         }  
     }  
     catch (IOException e) {  
         e.printStackTrace();  
         throw new RuntimeException("复制文件异常");  
     }  
     finally {  
         try {  
             if(fis!=null) fis.close();  
         }  
         catch (IOException e) {  
             e.printStackTrace();  
           throw new RuntimeException("读取流");  
         }  
  }            
}

字节流缓冲区

字节流缓冲区跟字符流缓冲区一样,也是为了提高效率。

  • read():会将字节byte()提升为int型值。

  • write():会将int类型转换为byte()类型,保留最后的8位。

管道流

管道流用于多进程间的通讯。示例如下:

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
public class PipeExample {

public static void main(String[] args) throws IOException {

final PipedOutputStream output = new PipedOutputStream();
final PipedInputStream input = new PipedInputStream(output);


Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
output.write("Hello world, pipe!".getBytes());
} catch (IOException e) {
}
}
});


Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
int data = input.read();
while(data != -1){
System.out.print((char) data);
data = input.read();
}
} catch (IOException e) {
}
}
});

thread1.start();
thread2.start();

}
}

参考文档:
Jenkov.com/java-io

更多Java基础系列文章,参见Java基础大纲

CATALOG
  1. 1. 分类
  2. 2. 字符流
    1. 2.1. 字符流读写:
    2. 2.2. 文件写出一例
    3. 2.3. 文件读入一例
    4. 2.4. 指定编码
  3. 3. 字符流的缓冲区:BufferedReader和BufferedWreiter
    1. 3.1. BufferedReader示例
    2. 3.2. BufferedWriter示例
  4. 4. 字节流
    1. 4.1. 文件复制示例
    2. 4.2. 字节流缓冲区
  5. 5. 管道流