Java IO

文件编码

如果直接复制文本内容会自动转换编码
ANSI并不是某一种特定的字符编码,而是在不同的系统中,ANSI表示不同的编码。比如在中文系统中使用gbk

当你的字节序列是某种编码时,这个时候想把字节序列变成字符串,也需要用这种编码方式,否则会出现乱码
文本文件本身可以是任意编码的字节序列,但在utf-8下创建的文本文件只能识别为utf-8的编码,复制文件到其他编码环境下会识别为乱码,复制文本内容会自动转换

.java文件中指定的各种编码格式,无论指定成哪种格式,最后在编译成.class时统统经过了 unicode 编码转换成双字节

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
String s = "你好word";
//Linux默认使用utf-8,locale命令查看
//IDE使用utf-8
//在UTF-8编码中,英文字符占一个字节,中文字符占用3个字节。
byte[] bytes = s.getBytes();
for(byte b :bytes){
//默认使用十进制
//System.out.print(b+" ");
//把字节转换成了int以16进制的方式显示,并去掉前24位(byte只占8位,转换为int,变为32位
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
byte[] bytes1 = s.getBytes("utf-8");
System.out.print("utf-8:\t\t");
for(byte b :bytes1){
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
//gbk中,英文字符占用一个字节,中文占用两个字节
byte[] bytes2 = s.getBytes("gbk");
System.out.print("gbk:\t\t");
for(byte b :bytes2){
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
//utf-16be中,英文字符占用两个字节,中文占用两个字节
byte[] bytes3 = s.getBytes("utf-16be");
System.out.print("utf-16be:\t");
for(byte b :bytes3){
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
System.out.println();
// 当你的字节序列是某种编码时,这个时候想把字节序列变成字符串
// 也需要用这种编码方式,否则会出现乱码
String string1 = new String(bytes3);
System.out.println(string1);
String string2 = new String(bytes3,"utf-16be");
System.out.println(string2);

File类

java.io.File类用于表示文件或目录的信息(名称、大小等),不能用于文件内容的访问

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
File file = new File("/home/lee/Downloads/Temple");
//分隔符
System.out.println(File.separator);
System.out.println(File.separatorChar);
//判断文件或目录是否存在
System.out.println(file.exists());
if(!file.exists()){
//创建文件,包括所有必需但不存在的父目录
file.mkdirs();
//创建文件
//file.mkdir();
}else{
//删除文件
file.delete();
}
//是否是一个目录,如果是目录返回true,如果不是目录或者目录不存在返回的是false
System.out.println(file.isDirectory());
//是否是一个文件,如果是文件返回true,如果不是文件或者文件不存在返回的是false
System.out.println(file.isFile());
File file1 = new File("/home/lee/Downloads/log1.txt");
//File file1 = new File("/home/lee/Downloads/","log1.txt")
if(!file1.exists()){
try {
//创建文件
file1.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println(file);//file.toString的内容
//文件或目录名
System.out.println(file.getName());
System.out.println(file1.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsolutePath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getParentFile());
System.out.println(file.getParent());
System.out.println(file1.getPath()); //路径名字符串,包括文件名
System.out.println(file1.getAbsolutePath());//绝对路径名,返回类型为File
System.out.println(file1.getAbsoluteFile());//绝对路径名,返回类型为String
//返回父目录的路径
System.out.println(file1.getParentFile()); //返回值为File
System.out.println(file1.getParent()); //返回值为String
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
/**
* 遍历目录,包括子目录
*/
public static void listDirectory(File file) throws IOException, IllegalAccessException {
if(!file.exists()){
throw new IllegalAccessException("目录"+file+"不存在");
}
if(!file.isDirectory()){
throw new IllegalAccessException(file+"不是目录");
}
//下列两个方法都是列出路径名表示的目录中的文件和目录,但返回值不同
String[] strings = file.list();
File[] files = file.listFiles();
if(files != null & files.length != 0){
for(File f:files){
if(f.isDirectory()){
listDirectory(f);
}else{
System.out.println(f.getPath());
}
}
}
}

RandomAccessFile类

RandomAccessFile类提供对文件内容的访问,既可以读文件,也可以写文件。支持随机访问文件,可以访问文件的任意位置。

  • 在硬盘上的文件是以 byte byte byte形式存储的,是数据的集合
  • RandomAccessFile打开文件有两种模式:rw(读写),r(只读)
  • 文件指针,打开文件时指针在开头 pointer = 0
  • 写方法:raf.write(int)只写一个字节(后8位),同时指针指向下一个位置,准备再次写入
  • 读方法:int b = raf.read()—>读一个字节
  • 文件读写完成以后一定要关闭raf.close()
  • 不存在追加,如果需要追加,将位置定位到文件末尾,使用long fileLen = raf.length(); raf.seek(fileLen);

IO流

IO流分为输入流、输出流,又分为字节流、字符流

字节流

InputStream和OutputStream是抽象类

  1. InputStream:抽象了应用程序读取数据的方式
  2. OutputStream:抽象了应用程序写出数据的方式
  3. EOF = End 读到-1就读到结尾

输入流基本方法

int b = in.read();
读取一个字节无符号填充到int低八位,如果已到达文件末尾,则返回 -1。
in.read(byte[] buf)
读取数据填充到字节数组buf
in.read(byte[] buf,int start, int size);
读取数据到字节数组buf从buf的start位置开始存放size长度的数据

输出流基本方法

out.write(int b)
写出一个byte到流,b的低8位
out.write(byte[] buf)
将buf字节数组都写到流
out.write(byte[] buf, int start,int size)
字节数组buf从start位置开始写size长度的字节到流

FileInputStream类

InputStream的子类,具体实现了在文件上读取数据

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
/**
* 读取指定文件内容,按照16进制输出到控制台
* 并且每输出10个byte换行
* 一个字节一个字节读取文件内容
*/
public static void printHex(String filename) throws IOException {
FileInputStream fis = new FileInputStream(filename);
int b;
int i = 0;
while((b=fis.read()) != -1){
System.out.print(Integer.toHexString(b & 0xff)+" ");
i++;
if(i% 10 == 0){
System.out.println();
}
}
}
/**
* 读取指定文件内容,按照16进制输出到控制台
* 并且每输出10个byte换行
* 一次性读取20 * 1024个字节读取文件内容
*/
public static void printHex1(String filename) throws FileNotFoundException,IOException {
FileInputStream fis = new FileInputStream(filename);
byte[] bytes = new byte[20 * 1024];
int b=0;
int j = 0;
while((b = fis.read(bytes,0,bytes.length)) != -1){
for(int i =0;i<bytes.length;i++){
System.out.print(Integer.toHexString(bytes[i] & 0xff)+" ");
j++;
if(j%10 == 0){
System.out.println();
}
}
}
}

字符流

对象的序列化和反序列化