Java之IO流

目录:

1.文件编码

2.File类

3.RandomAccessFile

4.字节流

5.字符流

6.对象的序列化和反序列化


1.文件编码

1)相关知识点
  • 八进制和十六进制的表示方式:八进制前面加0,比如:0123;十六进制前面加0x,比如:0x123;
  • gbk编码:中文占用2个字节,英文占用1个字节;
  • utf-8编码:中文占用3个字节,英文占用1个字节;
  • Java是双字节编码,Java里的一个字符占两个字节,utf-16be编码:中英文都占用2个字节
  • 当你的字节序列使用某种编码时,如果想把字节序列转成字符串,也需要使用这种编码方式,否则会出现乱码。
  • 文本文件,就是字节序列,可以是任意编码的字节序列,如果在中文机器上直接创建文件,那么该文本文件只认识ansi编码
2)相关API
    s.getBytes():字符串转成字节数组(参数为空,转换成字节序列是用项目默认的编码gbk)
   Integer.toHexString(byte b & 0xff):把字节(转成int)以16进制的方式显示,字节转成int(是在一个字节前面加32个1转成4个字节),这里可以和0xff做“位与”运算消除前面多余的显示
   new String(byte b):把字节序列转成字符串,使用项目默认编码gbk
   new String(byte b,"utf-16be"):把字节序列转成字符串,使用项目默认编码

3)相关练习

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
package corejava;
  
import java.io.UnsupportedEncodingException;
  
public class EncodeDemo {
  public static void main(String[] args) throws UnsupportedEncodingException {
    String s = "我爱ABC";
    byte[] bytes1 = s.getBytes("gbk");//不写编码,则使用平台的默认字符集将此 String 编码为 byte序列,并返回byte[].
    //s.getBytes(Charset charset) 使用给定的charset将此String编码到byte序列;
    //返回的是一个byte[]字节数组
      
    for(byte b: bytes1){
      System.out.print(Integer.toHexString(b&0xff)+" ");
      //Integer.toHexString(int i)以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式
    }
    //gbk编码中文占有两个字节,英文占有一个字节
    System.out.println();
    byte[] bytes2 = s.getBytes("utf-8");
    for(byte b: bytes2){
      System.out.print(Integer.toHexString(b&0xff)+" ");
    }
    //utf-8编码 中文占有三个字节,英文占有一个字节
    System.out.println();
    //java是双字节编码 --->utf-16be >> 中文和英文都占有两个字节
    byte[] bytes3 = s.getBytes("utf-16be");
    for(byte b: bytes3){
      System.out.print(Integer.toHexString(b&0xff)+" ");
    }
      
    /*当你的字节序列是某种编码时,这个时候想把字节序列变成
     *字符串,也需要用这种编码方式,否则会出现乱码
     * */
    System.out.println();
    String str1 = new String(bytes3);//用项目默认的编码即(GBK编码) ----->> bytes3在上面定义成“utf-16be”的编码了,所以会出现乱码
    System.out.println(str1);
    System.out.println();
      
    String str2 = new String(bytes3,"utf-16be");
    System.out.println(str2);
      
   /*
    * 文本文件就是字节序列
    * 可以是任意编码的字节序列
    * 如果我们在中文机器上直接创建文本文件,那么该文本文件只认识ansi编码
    *
   */
  }
}

2.File类

1)相关知识点
  • Java.io.File类用于表示文件(目录)
  • File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问
    
2)相关API(Alt+/快速查看API)
    new File("E:\\javaio"):创建File对象,因为\是转义字符,这里要用双斜杠"\\"或者反斜杠"/"
    new File("E:\\javaio","日记1.txt"):2个参数的构造方法
    new File("D:"+File.separator+"Study");//separator是专用的分隔符,File类的静态属性
    file.exists():判断目录(文件)存不存在
    file.mkdir():创建目录
    file.delete():删除目录、文件
    file.isDirectory():判断是否为目录
    file.isFile():判断是否为文件

file.createNewFile():创建新文件

file.getAbsolutePath():获取地址

file2.getName():获取目录名和文件名

file.getParent():获取父目录

3)相关练习
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
package corejava;
  
import java.io.File;
import java.io.IOException;
  
public class fileDemo {
      
    public static void main(String[] args) {
        File file=new File("D:\\javaio");//这里要用双斜杠
        //File file=new File("D:"+File.separator+"Study");//separator是专用的分隔符
        if (file.exists()) {
            file.mkdir();//创建目录
        }/*else {
            file.delete();//删除目录
        }*/
        //判断是否为目录
        System.out.println("是否为目录:"+file.isDirectory());
        //判断是否为文件
        System.out.println("是否为文件:"+file.isFile());
          
        //File file2=new File("D:/javaio/日记1.txt");
        File file2=new File("D:/javaio","日记1.txt");
        if (!file2.exists()) {
            try {
                file2.createNewFile();//创建新文件
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }else {
            file2.delete();
        }
        //常用的File对象的API
        System.out.println(file);//file.toString()的内容
        System.out.println(file.getAbsolutePath());//file.toString()的内容
        System.out.println(file.getName());//获取目录名或文件名
        System.out.println(file2.getName());//获取目录名或文件名
        System.out.println(file.getParent());//父目录    
    }
}
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
package corejava;
  
import java.io.File;
import java.io.IOException;
  
/**
 * File的工具类,进行过滤、遍历等操作
 * @author Administrator
 *
 */
public class FileUtils {
    public void ListDirectory(File file)throws IOException {
        if (!file.exists()) {
            throw new IllegalArgumentException("目录"+file+"不存在!!");
        }
        if (!file.isDirectory()) {
            throw new IllegalArgumentException(file+"不是目录!!");
        }
        //列出目录下的子目录和文件
            File[] files=file.listFiles();
            if (files.length<=0) {
                System.out.println("目录下没有文件!!");
            }else{
                for (File f : files) {
                    if (f.isFile()) {//判断是文件则打印
                        System.out.println(f);
                    }else {//不是文件则再次调用方法遍历
                        ListDirectory(f);
                    }
                }
            }
    }
}

3.RandomAccessFile 【file类相当于一本书(只有书的信息),而RandomAccessFile类相当于一个人(有读写等动作)】

1)相关知识点
    RandomAccessFile :Java提供的对文件内容访问的类,既可以读文件,也可以写文件,还可以随机访问文件,即可以访问文件的任意位置。
    Java文件模型:在硬盘上的文件都是byte存储的,是数据的集合
    打开文件:有两种模式“rw”(读写),“r”(只读)RandomAccessFile raf=new RandomAccessFile(file,"rw");
    指针:因为是支持随机读取,所以有个文件指针,打开文件时指针在开头 pointer=0;
    写方法:raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
    读方法:int b=raf.read();--->读一个字节,转为整数

关闭资源:文件读写完一定要关闭,否则会有意想不到的问题

2)相关API

new RandomAccessFile(file,mode):创建RandomAccessFile对象,对文件内容进行读写;其中mode可以是rw,或者r

raf.write():一次只写一个字节;

raf.read(bs):可以一次性读取全部内容到字节数组bs中;

Array.toString(bs):把某种形式的数组转为字符串;

new String(bs,"gbd"):按某种编码格式,把字节数组转成字符串;

raf.seek(0):将指针移动首尾

raf.close():关闭资源

3)相关练习

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
55
56
57
package corejava;
  
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
  
public class RafDemo {
  
    public static void main(String[] args)throws IOException {
        File dir=new File("Demo");//如果没有写绝对路径,就是项目的相对路径
        if (!dir.exists()) {
            dir.mkdir();
        }
        File file=new File(dir, "1.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        //创建RandomAccessFile对象,进行读写操作
        RandomAccessFile raf=new RandomAccessFile(file, "rw");
        System.out.println("当前指针位置:"+raf.getFilePointer());
        raf.write('A');
        System.out.println("当前指针位置:"+raf.getFilePointer());
        raf.write('B');
        System.out.println("当前指针位置:"+raf.getFilePointer());
          
        int i=0x7fffffff;//write方法每次只能写1个字节,如果要把i写进去,要写4次
        raf.write(i >>> 24);
        raf.write(i >>> 16);
        raf.write(i >>> 8);
        raf.write(i);
        System.out.println("当前指针位置:"+raf.getFilePointer());
          
        //可以直接写一个int
        raf.writeInt(i);
        System.out.println("当前指针位置:"+raf.getFilePointer());
          
        String s="中";
        byte[] b=s.getBytes("gbk");
        raf.write(b);
        System.out.println("当前文件的长度"+raf.length());
          
        //读文件,必须把指针移到头部
        raf.seek(0);
        //一次性读取,把文件的内容都读到字节数组中
        byte[] bs=new byte[(int)raf.length()];
        raf.read(bs);
        System.out.print(Arrays.toString(bs)+";");//把某种数组转成字符串
        for (byte c : bs) {
            System.out.print(Integer.toHexString(c & 0xff)+"  ");//以16进制的形式显示
        }
        String s2=new String(bs,"gbk");//按某种编码形式构造新的字符串
        System.out.println(s2);
        //关闭资源
        raf.close();
    }
}

4)步骤总结

a.创建RandomAccessFile对象,指定读写模式

b.进行读或写操作(读取时指针移动首位)

c.把字节数组转化为相应形式进行输出

d.关闭资源

4.字节流(InputStream,OutputStream)

1)相关知识点

InputStream、OutputStream:InputStream抽象了应用程序读取数据的方式;OutputStream抽象了应用程序写出数据的方式

FileInputStream、FileOutputStream:实现类

    DataInputStream、DataOutputStrea:包装了一些简便的方法;
    BufferedInputStream & BufferedOutputStream:这两个流类IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
FileOutputStream--->write()方法,相当于一滴一滴的把水转移过去
DataOutputStream--->writeXxx()方法会方便一些,相当于一瓢一瓢地把水转移过去
BufferedOutputStream--->writeXxx()方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入缸中,这样性能提高了

EOF=End    读到-1就读到结尾

2)相关API

输入流

int b=in.read();读取一个字节无符号填充到int低8位。-1是EOF

in.read(byte[] buf):读取数据填充到字节数组buf

in.read(byte[] buf,int start,int size):读取数据到字节数组buf,从buf的start开始存放size长度的数据

输出流

FileOutputStream fs=new FileOutputStream("Demo/1.dat"):如果文件不存在,则直接创建,如果存在,

上一篇:WPF制作带明细的环形图标


下一篇:StringUtils常用方法+StringUtils详细介绍