Java之IO流

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java之IO流相关的知识,希望对你有一定的参考价值。

目录:

技术分享1.文件编码

2.File类

3.RandomAccessFile

4.字节流



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.字节流

1)相关知识点

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

    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"):如果文件不存在,则直接创建,如果存在,删除后创建

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

              out.write(int b):写出一个byte到流,b的低8位

              out.write(byte[] buf):将buf字节数组都写到流

              out.write(byte[] buf,int start,int size):字节数组buf从start位置开始写size长度的字节到流

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package corejava;
   
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
   
public class IOUtil {
    /**
     * 读取指定文件内容,按照16进制输出到控制台,并且每输出10个byte换行
     * @param fileName
     * @throws IOException
     */
    public static void printHex(String fileName)throws IOException {//单字节读取
        FileInputStream fis=new FileInputStream(fileName);
        int b;
        int i=1;//用于换行,每10位换行
        while ((b=fis.read())!=-1) {
            if (b <= 0xf) {
                System.out.print("0");
            }
            System.out.print(Integer.toHexString(b)+"  ");
            if (i++%10==0) {
                System.out.println();
            }
        }
        fis.close();
    }
   
    public static void printHexByByte(String fileName)throws IOException {//多字节读取
        FileInputStream fis=new FileInputStream(fileName);
        byte[] buf=new byte[20 * 1024];
        int j=1;
        int length=fis.read(buf,0,buf.length);//将输入流读到byte数组(相当于一个缓存)中,返回读到的总长度
        for(int i=0;i<length;i++){
            if (buf[i]<=0xf) {
                System.out.print("0");
            }
            System.out.print(Integer.toHexString(buf[i] & 0xff)+"  ");
            if (j++%10==0) {
                System.out.println();
            }
        }
        fis.close();
    }
       
    public static void copyFile(File srcFile,File destFile)throws IOException {//文件复制,包含读写操作
        if (!srcFile.exists()) {
            throw new IllegalArgumentException("文件"+srcFile+"不存在!");
        }
        if (!srcFile.isFile()) {
            throw new IllegalArgumentException(srcFile+"不是文件!");
        }
        FileInputStream in=new FileInputStream(srcFile);
        FileOutputStream out=new FileOutputStream(destFile);
        byte[] buf=new byte[8*1024];
        int b;
        while ((b=in.read(buf, 0, buf.length))!=-1) {
            out.write(buf, 0, buf.length);
            out.flush();
        }
        in.close();
        out.close();
    }
}
   
//测试读取时间
public static void main(String[] args) {
        try {
            long start=System.currentTimeMillis();//开始时间
            IOUtil.printHex("D:\\javaio\\111.txt");
            //IOUtil.printHexByByte("D:\\javaio\\111.txt");
            long end=System.currentTimeMillis();//结束时间
            System.out.println();
            System.out.print(end-start);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void copyFileByBuffer(File srcFile,File destFile)throws IOException {//文件复制,利用缓冲
        if (!srcFile.exists()) {
            throw new IllegalArgumentException("文件"+srcFile+"不存在!");
        }
        if (!srcFile.isFile()) {
            throw new IllegalArgumentException(srcFile+"不是文件!");
        }
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile));
        int c;
        while ((c=bis.read())!=-1) {
            bos.write(c);
            bos.flush();
        }
        bis.close();
        bos.close();
    }

未完待续。。。



























以上是关于Java之IO流的主要内容,如果未能解决你的问题,请参考以下文章

java基础之 IO 流(输入/出字符流)

java基础之 IO 流(RandomAccessFile类)

java基础之 IO 流(InputStream/OutputStream)

Java之IO流总结

java基础之IO流

Java 之IO流及应用