一个很著名的奇怪现象:当你在 windows 的记事本里新建一个文件,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是几个乱码!呵呵,有人说这就是联通之所以拼不过移动的原因。
其实这是因为GB2312编码与UTF8编码产生了编码冲撞的原因。
GB系中“联通”的二进制编码为:11000001 10101010 11001101 10101000
注意到了吗?第一二个字节、第三四个字节的起始部分的都是"110"和"10",正好与UTF8规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了"0000 0000 0110 1010",不好意思,这是UNICODE的006A,也就是小写的字母"j",而之后的两字节用UTF8解码之后是0368,这个字符什么也不是。这就是只有"联通"两个字的文件没有办法在记事本里正常显示的原因。
而如果你在"联通"之后多输入几个字,其他的字的编码不见得又恰好是110和10开始的字节,这样再次打开时,记事本就不会坚持这是一个utf8编码的文件,而会用ANSI的方式解读之,这时乱码又不出现了。
package com.imooc.io;
import java.io.UnsupportedEncodingException;
/**
* Created by N3verL4nd on 2017/3/8.
*/
public class EncodeDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "慕课ABC";
byte[] bytes = str.getBytes("GBK");
//gbk编码中文占用两个字节,英文占用1个字节
for (byte b : bytes) {
//把字节(转换成了int)以16进制的方式显示
System.out.print(Integer.toHexString(b & 0xff) + " ");
}
/**
* 当你的字节序列使用某种编码时,如果把字节序列转化为
* 字符串,也需要使用相同的编码方式,否则出现乱码
*/
System.out.println(new String(bytes));//用项目默认的编码方式
System.out.println("\n" + new String(bytes, "UTF-8"));
System.out.println(new String(bytes, "GBK"));
bytes = str.getBytes("UTF-8");
//UTF-8编码中文占用三个字节,英文占用1个字节
for (byte b : bytes) {
System.out.print(Integer.toHexString(b & 0xff) + " ");
}
System.out.println("\n" + new String(bytes));
//java是双字节编码 UTF-16BE
bytes = str.getBytes("UTF-16BE");
//utf-16be 中文占用2个字节,英文占用两个字节
for (byte b : bytes) {
System.out.print(Integer.toHexString(b & 0xff) + " ");
}
System.out.println("\n" + new String(bytes, "UTF-16BE"));
/**
* 文本文件保存的字节序列
* 可以死任意编码的字节序列
* 在中文机器上创建的文本文件默认是ANSI
*/
}
}
参考:
http://www.iteedu.com/topic/charset/utf8.php
http://oznyang.iteye.com/blog/30692
https://www.zhihu.com/question/25367290
作用:用于表示文件(目录),只能表示文件(目录)的信息,不能用于文件的访问。
package com.imooc.io;
import java.io.File;
import java.io.IOException;
/**
* Created by N3verL4nd on 2017/3/9.
*/
public class FileDemo {
public static void main(String[] args) {
File file = new File("D:/Java/IdeaProjects/JavaProj/JTest/src/com/imooc/io/doc");
//System.out.println(file.isDirectory());
if (!file.exists()) {
file.mkdir();
System.out.println("路径 " + file.getAbsolutePath() + " 被创建!");
} else {
file.delete();
System.out.println("路径 " + file.getAbsolutePath() + " 被删除!");
}
file = new File("D:/Java/IdeaProjects/JavaProj/JTest/src/com/imooc/io/doc.txt");
//file = new File("D:/Java/IdeaProjects/JavaProj/JTest/src/com/imooc/io/", "doc.txt");
//System.out.println(file.isFile());
if (!file.exists()) {
try {
//创建文件
file.createNewFile();
System.out.println("文件 " + file.getName() + " 被创建!");
} catch (IOException e) {
e.printStackTrace();
}
} else {
//删除文件
file.delete();
System.out.println("文件 " + file.getName() + " 被删除!");
}
}
}
package com.imooc.io;
import java.io.File;
/**
* Created by N3verL4nd on 2017/3/9.
* 列出File类的一些常用操作,比如过滤、遍历等
*/
public class FileUtils {
/**
* 列出指定目录下(包括其子目录)的所有文件
* @param file
*/
public static void listDirectory(File file) throws IllegalArgumentException {
if (!file.exists()) {
throw new IllegalArgumentException("目录 " + file + " 不存在!");
}
if (!file.isDirectory()) {
throw new IllegalArgumentException(file + " 不是目录!");
}
/*//返回字符串数组,包括该目录下的目录名和文件名,不包括子目录
for (String patName : file.list()) {
System.out.println(file + "\\" + patName);
}*/
for (File f : file.listFiles()) {
if (f.isFile()) {
System.out.println("[文件]:" + f);
} else if (f.isDirectory()) {
System.out.println("[目录]:" + f.getAbsolutePath());
listDirectory(f);
}
}
}
}
其封装由文件指针
3、写方法
raf.write(int)-->只写1个字节(后8位),同时文件指针指向下一个位置
4、读方法
int b = raf.read() --->读一个字节
5、文件读写完成后一定要关闭
raf.close();
package com.imooc.io; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Arrays; /** * Created by N3verL4nd on 2017/3/9. */ public class rafDemo { public static void main(String[] args) throws IOException { File file = new File("JTest/doc.txt"); if (!file.exists()) file.createNewFile(); RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); //指针的位置 System.out.println(randomAccessFile.getFilePointer()); randomAccessFile.write('A');//只写了1个字节 'A'-->65-->01000001 System.out.println(randomAccessFile.getFilePointer()); randomAccessFile.write('B'); System.out.println(randomAccessFile.getFilePointer()); int x = 0x7fffffff; randomAccessFile.write(x >>> 24);//高8位 randomAccessFile.write(x >>> 16); randomAccessFile.write(x >>> 8); randomAccessFile.write(x); System.out.println(randomAccessFile.getFilePointer()); //randomAccessFile.writeInt(x); randomAccessFile.write("李广辉".getBytes()); System.out.println("文件长度:" + randomAccessFile.length()); //读文件,必须把指针移到头部 randomAccessFile.seek(0); byte[] buf = new byte[(int) randomAccessFile.length()]; randomAccessFile.read(buf); System.out.println(Arrays.toString(buf)); for (byte b : buf) { System.out.print(Integer.toHexString(b & 0xff) + " "); } System.out.println(); System.out.println(new String(buf, "UTF-8")); randomAccessFile.close(); } }
InputStream:抽象了应用程序读取数据的方式
OutputStream:抽象了应用程序写入数据的方式
EOF end of file:读到-1就读到了结尾
输入流的基本方法:
int b = in.read();读取一个字节无符号填充到int低八位
in.read(byte[] buf);读取数据填充到字节数组buf
in.read(byte[] buf, int start, int size);读取数据填充到字节数组buf,从buf的start位置开始,存放size长度的数据。
输出流:
out.write(int b);写出1个byte到流,b的低八位
out.write(byte[] buf)将buf字节数组都写入到流
out.write(byte[] buf, int start, int size);
FileInputStream-->具体实现了在文件上的输入操作
package com.imooc.io; import java.io.FileInputStream; import java.io.IOException; /** * Created by N3verL4nd on 2017/3/10. */ public class IOUtil { /** * 读取指定文件内容,按照16进制输出到控制台 * 并且每输出10额byte换行 * @param fileName */ public static void printHex(String fileName) throws IOException { //把文件作为字节流进行读操作 FileInputStream in = new FileInputStream(fileName); int b; int i = 1; while ((b = in.read()) != -1) { i++; if (b <= 0xf) { //单位数前面补0 System.out.print("0"); } System.out.print(Integer.toHexString(b) + " "); if (i % 10 == 0) { System.out.println(); } } in.close(); } public static void printHexByByteArray(String fileName) throws IOException{ FileInputStream in = new FileInputStream(fileName); byte[] buf = new byte[20 * 1024]; /** * 从in中批量读取字节,放入buf这个字节数组中 * 从第0个位置开始做,最多放buf.length个字节 * 返回的是读到的字节的个数 */ /*int bytes = in.read(buf, 0, buf.length); int j = 1; for (int i = 0; i < bytes; i++) { j++; if (buf[i] <= 0xf) { System.out.print("0"); } System.out.print(Integer.toHexString(buf[i]) + " "); if (j % 10 == 0) { System.out.println(); } }*/ int bytes; while ((bytes = in.read(buf, 0, buf.length)) != -1) { int j = 1; for (int i = 0; i < bytes; i++) { j++; if (buf[i] <= 0xf) { System.out.print("0"); } System.out.print(Integer.toHexString(buf[i] & 0xff) + " "); if (j % 10 == 0) { System.out.println(); } } } } }FileOutputStream实现了向文件写出byte数据的方法
package com.imooc.io; import java.io.FileOutputStream; import java.io.IOException; /** * Created by N3verL4nd on 2017/3/10. */ public class FileOutDemo { public static void main(String[] args) throws IOException { //如果该文件不存在,则直接创建,如果不存在,则删除后创建 FileOutputStream out = new FileOutputStream("D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt"); //out.write('A'); //out.write('B'); int x = 3389; out.write(x >>> 24); out.write(x >>> 16); out.write(x >>> 8); out.write(x); //out.write("中国".getBytes()); IOUtil.printHex("D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt"); out.close(); } }
package com.imooc.io; import java.io.*; /** * Created by N3verL4nd on 2017/3/10. */ public class FileCopy { public static void Copy(File src, File dst) throws IOException { if (!src.exists()) { throw new IllegalArgumentException(src + "不存在!"); } if (!src.isFile()) { throw new IllegalArgumentException(src + "不是文件!"); } FileInputStream in = new FileInputStream(src); FileOutputStream out = new FileOutputStream(dst); int len; byte[] buf = new byte[1024]; while ((len = in.read(buf, 0, 1024)) != -1) { out.write(buf, 0, len); } in.close(); out.close(); } public static void main(String[] args) { try { Copy(new File("D:\\N3verL4nd\\Desktop\\Pro.txt"), new File("D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt")); } catch (IOException e) { e.printStackTrace(); } } }
DataOutputStream/DataInputStream
对流功能的扩展,可以更加方便的读取int,long,字符等类型的数据
DataOutputStream
writeInt(),writeDouble(),writeUTF()
package com.imooc.io; import java.io.*; /** * Created by N3verL4nd on 2017/3/11. */ public class DosDemo { public static void main(String[] args) throws IOException { String filename = "D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt"; DataOutputStream out = new DataOutputStream(new FileOutputStream(filename)); out.writeInt(100); out.writeDouble(1.1); //采用UTF-8编码写出 out.writeUTF("你好"); //采用UTF-16BE编码写出 out.writeChars("中国"); out.close(); // IOUtil.printHex(filename); DataInputStream in = new DataInputStream(new FileInputStream(filename)); System.out.println(in.readInt()); System.out.println(in.readDouble()); System.out.println(in.readUTF()); System.out.println(in.readChar()); System.out.println(in.readChar()); in.close(); } }BufferedInputStream/BufferedOutputStream
这两个流为IO提供了带缓冲区的操作,一般打开文件进行读写都会加上缓冲区,从而提高IO性能。
文本和文本文件:
java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
文件是byte byte byte的数据序列
文本文件是文本序列按照某种编码方案(UTF-8/UTF-16BE,GBK)序列化为byte的存储文件
字符流(Reader和Writer)
字符的处理,一次处理一个字符
字符的底层仍然是基本的字节序列
字符流的基本实现
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWriter 提供char流到byte流,按照编码处理
package com.imooc.io;
import java.io.*;
/**
* Created by N3verL4nd on 2017/3/12.
*/
public class OSWDemo {
public static void main(String[] args) {
String fileName = "D:\\N3verL4nd\\Desktop\\Pro.txt";
InputStreamReader isr = null;//默认项目编码
try {
isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
} catch (UnsupportedEncodingException | FileNotFoundException e) {
e.printStackTrace();
}
/*try {
int c;
while ((c = isr.read()) != -1) {
System.out.print((char)c);
}
isr.close();
} catch (IOException e) {
e.printStackTrace();
}*/
char[] buf = new char[1024];
int len;
try {
//批量读取,放入buffer这个字符数组,从第0个位置开始,最多放1024个
//返回读取字符的个数
while ((len = isr.read(buf, 0, 1024)) != -1) {
System.out.print(new String(buf, 0, len));
}
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReder/FileWriter继承自InputStreamReader/OutputStreamWriter,使其对文件读写更加方便。
package com.imooc.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by N3verL4nd on 2017/3/12.
*/
public class FRFW {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:\\N3verL4nd\\Desktop\\Pro.txt");
int c;
while ((c = reader.read()) != -1) {
System.out.println(c);
}
reader.close();
}
}
字符流的过滤器
BufferedReader -->readLine 一次读一行
BufferedWriter -->writeLine一次写一行
package com.imooc.io;
import java.io.*;
/**
* Created by N3verL4nd on 2017/3/10.
*/
public class FileCopy {
public static void Copy(File src, File dst) throws IOException {
if (!src.exists()) {
throw new IllegalArgumentException(src + "不存在!");
}
if (!src.isFile()) {
throw new IllegalArgumentException(src + "不是文件!");
}
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
int len;
byte[] buf = new byte[1024];
while ((len = in.read(buf, 0, 1024)) != -1) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
public static void CopyFileByBuffer(File src, File dst) throws IOException {
if (!src.exists()) {
throw new IllegalArgumentException(src + "不存在!");
}
if (!src.isFile()) {
throw new IllegalArgumentException(src + "不是文件!");
}
BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dst));
int len;
byte[] buf = new byte[1024];
while ((len = in.read(buf, 0, 1024)) != -1) {
out.write(buf, 0, len);
// out.flush();//刷新缓冲区
}
in.close();
out.close();
}
public static void main(String[] args) {
try {
long start = System.currentTimeMillis();
CopyFileByBuffer(new File("F:\\H4ck\\bjut\\db.html"), new File("D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt"));
//Copy(new File("F:\\H4ck\\bjut\\db.html"), new File("D:\\Java\\IdeaProjects\\JavaProj\\JTest\\doc.txt"));
long end = System.currentTimeMillis();
System.out.println(end - start);
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.imooc.io; import java.io.*; /** * Created by N3verL4nd on 2017/3/12. */ public class BRBW { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream("D:\\N3verL4nd\\Desktop\\Pro.txt") )); while (reader.ready()) { System.out.println(reader.readLine()); } reader.close(); } }
package com.imooc.io; import java.io.Serializable; /** * Created by N3verL4nd on 2017/3/12. */ public class Student implements Serializable{ private String stuNO; private String name; private int age; public Student() { } public Student(String stuNO, String name, int age) { this.stuNO = stuNO; this.name = name; this.age = age; } public String getStuNO() { return stuNO; } public void setStuNO(String stuNO) { this.stuNO = stuNO; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "stuNO='" + stuNO + '\'' + ", name='" + name + '\'' + ", age=" + age + '}'; } }
package com.imooc.io; import java.io.*; /** * Created by N3verL4nd on 2017/3/12. */ public class ObjectSerializable { public static void main(String[] args) { String fileName = "D:\\Java\\IdeaProjects\\JavaProj\\JTest\\src\\com\\imooc\\io\\doc\\data.dat"; Student student = new Student("10010", "lgh", 24); try { //对象的序列化 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName)); //把student对象保存起来 out.writeObject(student); out.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName)); Student stu = (Student) in.readObject(); System.out.println(stu); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
private transient int age;//该元素不会进行虚拟机默认的序列化工作
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { elementData = EMPTY_ELEMENTDATA; // Read in size, and any hidden stuff s.defaultReadObject(); // Read in capacity s.readInt(); // ignored if (size > 0) { // be like clone(), allocate array based upon size not capacity ensureCapacityInternal(size); Object[] a = elementData; // Read in all elements in the proper order. for (int i=0; i<size; i++) { a[i] = s.readObject(); } } }
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff int expectedModCount = modCount; s.defaultWriteObject(); // Write out size as capacity for behavioural compatibility with clone() s.writeInt(size); // Write out all elements in the proper order. for (int i=0; i<size; i++) { s.writeObject(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }
package com.imooc.io; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; /** * Created by N3verL4nd on 2017/3/12. */ public class Student implements Serializable{ private String stuNO; private String name; private transient int age;//该元素不会进行虚拟机默认的序列化工作 public Student() { } public Student(String stuNO, String name, int age) { this.stuNO = stuNO; this.name = name; this.age = age; } public String getStuNO() { return stuNO; } public void setStuNO(String stuNO) { this.stuNO = stuNO; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "stuNO='" + stuNO + '\'' + ", name='" + name + '\'' + ", age=" + age + '}'; } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ //按照jvm默认序列化的元素进行序列化操作 s.defaultWriteObject(); //自己完成age的序列化操作 s.writeInt(age); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); this.age = s.readInt(); } }
transient Object[] elementData; // non-private to simplify nested class access
package com.imooc.io; import java.io.*; /** * Created by N3verL4nd on 2017/3/12. */ class A{ public A() { System.out.println("A"); } } class B extends A implements Serializable{ public B() { System.out.println("B"); } } class C extends B{ public C() { System.out.println("C"); } } public class Demo { public static void main(String[] args) { C c = new C(); try { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.dat")); out.writeObject(c); out.close(); System.out.println("---------------------"); ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.dat")); in.readObject(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }