JAVA中文件的读写 I/O 输入输出流

Posted 初心不变1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中文件的读写 I/O 输入输出流相关的知识,希望对你有一定的参考价值。

主要内容

1.编码问题

2.File类的使用

3.RandomAccessFile的使用

4.I/O 输入输出流

编码问题:

 1 import java.io.UnsupportedEncodingException;
 2 
 3 public class 编码问题 {
 4     public static void main(String[] args) {
 5         // 我们项目的默认编码是GBK
 6         String s = "测试 ABC";
 7         byte[] byte1 = s.getBytes();// 转换成的字节序列用的是项目默认的编码gbk
 8         for (byte b : byte1) {
 9             // 1 byte = 8 位 //toHexString这个函数是把字节(转换成了Int)以16进制的方式显示
10             System.out.print(Integer.toHexString(b & 0xff) + " ");// &
11                                                                     // 0xff是为了把前面的24个0去掉只留下后八位
12         }
13 
14         try {
15             // 也可以转换成指定的编码
16             byte[] bytes1 = s.getBytes("gbk");
17             System.out.println(new String(bytes1));
18         } catch (UnsupportedEncodingException e) {
19             // TODO Auto-generated catch block
20             e.printStackTrace();
21         }
22         /**
23          * gbk编码: 中文占用两个字节,英文占用一个字节 utf-8编码:中文占用三个字节,英文占用一个字节
24          * java是双字节编码,是utf-16be编码 utf-16be编码:中文占用两个字节,英文占用两个字节
25          * 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码
26          */
27         try {
28             byte[] byte2 = s.getBytes("utf-16be");
29             String s2 = new String(byte2, "utf-16be");
30             System.out.println(s2);
31         } catch (UnsupportedEncodingException e) {
32             // TODO Auto-generated catch block
33             e.printStackTrace();
34         }
35         /**
36          * 文本文件就是字节序列,可以是任意编码的字节序列
37          * 如果我们在中文机器上直接创建文本文件,那么该文件只认识ANSI编码(例如直接在电脑中创建文本文件)
38          */
39 
40         /**
41          * byte转int的时候为什么非要先&0xff计算出来才是正确答案?
42          * 首先,java中的二进制采用的是补码形式,并非原码或反码,这3个概念要搞清楚;
43          * 其次,byte占8位,int占32位,将byte强制转换为int型时,如果没有做 &
44          * 0xff运算,且byte对应的值为负数的话,就会对高位3个字节进行补位,这样就有可能出现补位误差的错误。
45          * 举例来说,byte型的-1,其二进制(补码)为11111111(即0xff),转换成int型,值也应该为-1,但经过补位后,
46          * 得到的二进制为11111111111111111111111111111111(即0xffffffff),这就不是-1了,对吧?
47          * 而0xff默认是int型,所以,一个byte跟0xff相与,会先将那个byte转化成int型运算,这样,结果中的高位3个字节就总会被清0,
48          * 于是结果就是我们想要的了~
49          */
50 
51     }
52 
53 }
View Code

File类的使用:

JAVA.io.File类用于表示文件(目录)
File类只用于表示文件( 目录)的信息(名称、大小等),不能用于文件内容的访问
File类的常用API:
1.创建File对象:File file=new File(String path);注意:File.seperater();获取系统分隔符,如:”\\“.
2.boolean file.exists();是否存在.
3.file.mkdir();或者file.mkdirs();创建目录或多级目录。
4.file.isDirectory()或者file.isFile()判断是否是目录或者是否是文件。
5.file.delete();删除文件或目录。
6.file.createNewFile();创建新文件。
7.file.getName()获取文件名称或目录绝对路径。
8.file.getAbsolutePath()获取绝对路径。
9.file.getParent();获取父级绝对路径。
10.file.getSize();获取文件大小。
11.file.getFormat();获取文件格式名。
 1 import java.io.File;
 2 import java.io.IOException;
 3 
 4 public class FileDemo {
 5 
 6     /**
 7      * @param args
 8      */
 9     public static void main(String[] args) {
10         // 了解构造函数的情况 查帮助ALT+/
11         File file = new File("E:\\\\javaio\\\\imooc");
12         // 判断文件/文件夹是否存在
13         // System.out.println(file.exists());
14         if (!file.exists())
15             file.mkdir(); // file.mkdirs()如果文件不存在,直接创建文件夹
16         // mkdir创建的一级目录,如果需要创建多级目录可以使用mkdirs()
17         else
18             file.delete();
19 
20         // 是否是一个目录 如果是目录返回true,如果不是目录or目录不存在返回的是false
21         System.out.println(file.isDirectory());
22         // 是否是一个文件
23         System.out.println(file.isFile());
24 
25         // File file2 = new File("e:\\\\javaio\\\\日记1.txt");
26         File file2 = new File("e:\\\\javaio", "日记1.txt");
27         if (!file2.exists())
28             try {
29                 file2.createNewFile();
30             } catch (IOException e) {
31                 // TODO Auto-generated catch block
32                 e.printStackTrace();
33             }
34         else
35             file2.delete();
36         // 常用的File对象的API
37         System.out.println(file);// file.toString()的内容
38         System.out.println(file.getAbsolutePath());
39         System.out.println(file.getName());
40         System.out.println(file2.getName());
41         System.out.println(file.getParent());
42         System.out.println(file2.getParent());
43         System.out.println(file.getParentFile().getAbsolutePath());
44     }
45 
46 }
FileDemo

遍历目录

 1 import java.io.File;
 2 import java.io.IOException;
 3 
 4 //列出File的一些常用操作比如过滤,遍历等操作
 5 public class FileUtils {
 6     /**
 7      * 列出指定指定目录下(包括其子目录)的所有文件
 8      * 
 9      * @param dir
10      * @throws IOException
11      */
12     public static void listDirectory(File dir) throws IOException {
13         if (!dir.exists()) {
14             throw new IllegalArgumentException("目录:" + dir + "不存在");
15         }
16         if (!dir.isDirectory()) {
17             throw new IllegalArgumentException(dir + "不是目录");
18         }
19 
20         // String[] fileNames =
21         // dir.list();//返回的是字符串数组,list()方法用于列出当前目录下的子目录和文件,直接子的名称,不包含子目录下的内容
22         // for (String string : fileNames) {
23         // System.out.println(dir+"\\\\"+string);
24         // }
25         //
26         // 如果要遍历子目录下的内容就需要构造成File对象做递归操作,File提供了直接返回File对象的API
27         File[] files = dir.listFiles();// 返回的是直接子目录(文件)的抽象
28         if (files != null && files.length > 0) {// 确定存在子目录
29             for (File file : files) {
30                 if (file.isDirectory()) {
31                     // 递归
32                     listDirectory(file);
33                 } else {
34                     System.out.println(file);
35                 }
36             }
37         }
38     }
39 }
FileUtils

RandomAccessFile的使用

RandomAccessFile JAVA提供的对文件内容的访问,既可以读文件,也可以写文件。
RandomAccessFile支持随机访问文件,可以访问文件的任意位置
(1)JAVA文件模型
在硬盘上的文件是byte byte byte存储的,是数据的集合
(2)打开文件
有两种模式"rw"(读写) "r"(只读)
RandomAccessFile raf = new RandomeAccessFile(file,"rw")
文件指针,打开文件时指针在开头 pointer = 0;
(3) 写方法
raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
提供和很多方法能够一次读写一个基本类型的数据
(4)读方法
int b = raf.read()--->读一个字节
(5)文件读写完成以后一定要关闭(Oracle官方说明)
 1 import java.io.File;
 2 import java.io.IOException;
 3 import java.io.RandomAccessFile;
 4 import java.util.Arrays;
 5 
 6 public class RafDemo {
 7 
 8     /**
 9      * @param args
10      */
11     public static void main(String[] args) throws IOException {
12         File demo = new File("demo");
13         if (!demo.exists())
14             demo.mkdir();
15         File file = new File(demo, "raf.dat");
16         if (!file.exists())
17             file.createNewFile();
18 
19         RandomAccessFile raf = new RandomAccessFile(file, "rw");
20         // 指针的位置
21         System.out.println(raf.getFilePointer());
22 
23         raf.write(\'A\');// 只写了一个字节
24         System.out.println(raf.getFilePointer());
25         raf.write(\'B\');
26 
27         int i = 0x7fffffff;
28         // 用write方法每次只能写一个字节,如果要把i写进去就得写4次
29         raf.write(i >>> 24);// 高8位
30         raf.write(i >>> 16);
31         raf.write(i >>> 8);
32         raf.write(i);
33         System.out.println(raf.getFilePointer());
34 
35         // 可以直接写一个int
36         raf.writeInt(i);
37 
38         String s = "中";
39         byte[] gbk = s.getBytes("gbk");
40         raf.write(gbk);
41         System.out.println(raf.length());
42 
43         // 读文件,必须把指针移到头部
44         raf.seek(0);
45         // 一次性读取,把文件中的内容都读到字节数组中
46         byte[] buf = new byte[(int) raf.length()];
47         raf.read(buf);
48 
49         System.out.println(Arrays.toString(buf));
50         for (byte b : buf) {
51             System.out.println(Integer.toHexString(b & 0xff) + " ");
52         }
53         raf.close();
54     }
55 
56 }
RafDemo
import java.io.IOException;
import java.io.RandomAccessFile;

public class RafReadDemo {

    /**
     * @param args
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        RandomAccessFile raf = new RandomAccessFile("demo/raf.dat", "r");
        raf.seek(2);
        int i = 0;
        int b = raf.read();// 读取到一个字节
        System.out.println(raf.getFilePointer());
        i = i | (b << 24);
        b = raf.read();
        i = i | (b << 16);
        b = raf.read();
        i = i | (b << 8);
        b = raf.read();
        i = i | b;
        System.out.println(Integer.toHexString(i));
        raf.seek(2);
        i = raf.readInt();
        System.out.println(Integer.toHexString(i));
        raf.close();
    }
}
RafReadDemo
序列化与基本类型序列化
1)将类型int 转换成byte或将其他数据类型转换成byte的过程叫序列化
数据---->n byte
2)反序列化
将n个byte 转换成一个数据的过程
nbyte ---> 数据
3)RandomAccessFile提供基本类型的读写方法,可以将基本类型数据
序列化到文件或者将文件内容反序列化为数据
 1 import java.io.File;
 2 import java.io.IOException;
 3 import java.io.RandomAccessFile;
 4 public class RandomAccessFileSeriaDemo {
 5 
 6     /**
 7      * @param args
 8      */
 9     public static void main(String[] args) throws IOException {
10         // TODO Auto-generated method stub
11         File demo = new File("demo1");
12         if (!demo.exists())
13             demo.mkdir();
14         File file = new File(demo, "raf.dat");
15         if (!file.exists())
16             file.createNewFile();
17         // 打开文件,进行随机读写
18         RandomAccessFile raf = new RandomAccessFile(file, "rw");
19         /* 序列化 */
20         int i = 0x7ffffff;
21         raf.write(i >>> 24);
22         raf.write(i >>> 16);
23         raf.write(i >>> 8);
24         raf.write(i);
25         System.out.println(raf.getFilePointer());
26 
27         /* 反序列化 */
28         raf.seek(0);
29         int b = raf.read();
30         i = i | (b << 24);
31         b = raf.read();
32         i = i | (b << 16);
33         b = raf.read();
34         i = i | (b << 8);
35         b = raf.read();
36         i = i | b;
37         System.out.println(Integer.toHexString(i));
38         raf.close();
39     }
40 }
41 
42 RandomAccessFileSeriaDemo
RandomAccessFileSeriaDemo

I/O 输入输出流

流的定义:

流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能。

这根用于数据传输的管道就是流,流就是一根管道

输入时,程序在源(文件,网络,内存)上打开一个流,然后如图一个一个顺序读。写也一样。

流的分类和使用:

四大基本抽象流,文件流,缓冲流,转换流,数据流,Print流,Object流。

JAVA.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同角度对其进行分类:

*按数据流的方向不用可以分为输入流和输出流

*按处理数据单位不同可以分为字节流和字符流

*按照功能不同可以分为节点流和处理流

JAVA中所提供的的所有流类型位于包JAVA.io内,都分别继承自以下四种抽象流类型:

节点流与处理流:

节点流可以从一个特定的数据源(节点)读取数据(如:文件,内存)

处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

节点流也叫原始流,处理流也叫包裹流。

 

流与类的关系:

如果一个类是用作设备和程序之间的数据传输,则这个类有一个新的名字叫做流

流一定是类,但类不一定是流

 

四大基本流的介绍

输入流,输出流,字节流,字符流

InputStream和OutputStream读写数据的单位是一个字节

Reader和Writer读写数据的单位是一个字符

在JAVA中一个字符占两个字节

InputStream,OutputStream,Reader,Writer都是抽象类,或者说都是抽象流,通常我们使用的都是它们的子类,凡是以Stream结尾的都是字节流。

 

InputStream 流中的常用方法:

 

 

OutputStream 流中的常用方法:

 

Reader 流中的常用方法:

 

 Writer 流中的常用方法:

 

 

文件流

 文件流包括:

FileInputStream FileOutputStream --字节流

FileReader FileWriter --字符流

实例:读取一个文件的内容并将其输出到显示器上,并统计读取的字节个数

 1 /*
 2     利用FileReader流来读取一个文件中的数据,并在显示器上输出!
 3 */
 4 
 5 import java.io.*;
 6 
 7 public class TestFileReader {
 8     public static void main(String[] args) {
 9         FileReader fr = null;
10 
11         try {
12             fr = new FileReader("C:\\\\Documents and Settings\\\\others\\\\桌面\\\\java\\\\TestFileReader.java");
13             int cnt = 0;
14             int ch;
15 
16             while (-1 != (ch = fr.read())) // 20行
17             {
18                 System.out.print((char) ch); // System.out.print(int ch);
19                                                 // 这是在显示器上输出ch的整数值,所以必须的进行类型转化,我们需要输出的是ch所代表的整数对应的字符
20                 ++cnt;
21             }
22 
23             System.out.printf("总共从TestFileReader.java文件中读取了%d个字符", cnt);
24         } catch (FileNotFoundException e) {
25             System.out.println("找不到文件!");
26             System.exit(-1);
27         } catch (IOException e) {
28             System.out.println("文件读取失败!");
29             System.exit(-1);
30         }
31     }
32 }
View Code

 

FileInputStream的使用

 

FileReader的使用

字节流与字符流的区别:

FileInputStream 和FileOutputStream 可以完成所有格式文件的复制

FileReader和FileWriter只可以完成文本文件的复制,却无法完成其他格式文件的复制

因为字节是不需要解码和编码的,将字节转化为字符才存在解码和编码的问题

字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据

实例:编程实现文件的复制

 1 /*
 2     利用FileInputStream 和 FileOutputStream 可以完成所有格式文件的赋值
 3     因为字节是不需要解码和编码的,将字节转化为字符才存在解码的问题
 4     本程序完成了音频文件的复制
 5 */
 6 
 7 import java.io.*;
 8 
 9 public class TestFileInputStreamOutputStreamCopy {
10     public static void main(String[] args) {
11         FileInputStream fi = null;
12         FileOutputStream fo = null;
13 
14         try {
15             fi = new FileInputStream("E:\\\\综艺\\\\歌曲\\\\卡农.mp3");
16             fo = new FileOutputStream("d:/share/Output.txt"); //使用播放器可正常播放该文件
17             int ch;
18 
19             while (-1 != (ch = fi.read())) {
20                 fo.write(ch);
21             }
22         } catch (FileNotFoundException e) {
23             System.out.println("文件没有找到!");
24             System.exit(-1);
25         } catch (IOException e) {
26             System.out.println("文件读写错误!");
27             System.exit(-1);
28         } finally {
29             try {
30                 if (null != fi) {
31                     fi.close();
32                     fi = null;
33                 }
34                 if (null != fo) {
35                     fo.close();
36                     fo = null;
37                 }
38             } catch (Exception e) {
39                 e.printStackTrace();
40                 System.exit(-1);
41             }
42         }
43 
44         System.out.println("文件复制成功!");
45     }
46 }
TestFileInputStreamOutputStreamCopy以上是关于JAVA中文件的读写 I/O 输入输出流的主要内容,如果未能解决你的问题,请参考以下文章

Java输入及输出处理(I/O流)

java—— IO 输入流输出流

I/O流

Java笔记:流I/O

Java输入输出流

Java 输入输出流