1.java的I/O操作
太痛苦了,这部分总是出问题,今天花了以上午的时间好好理了理思路,在这里做个笔记。java的I/O,我可以粗放的分为两种类型,一种是对文本文件的I/O(此时需要注意编码方式,否则容易文字乱码),另外一种就是对其他文件的I/O操作(此时一般采用字节流)。
先附上一张网上找来的图:
(1)首先说读取文件:
①读: FileInputStream :文件输入流(最底层的工具,字节流,这个可以读取所有的文件,但都是以二进制的方式读取,没有做任何封装),对应read()–> (char)fs.read(),read(byte[]) --> new String(byte[])
InputStream fis = new FileInputStream(“d:/a.txt”);
int read = fis.read(); // 读一个字节,并将这个字节转成整数返回,如果读完文件末尾最后一个字节,你还读,就返回 -1
byte[] buf = new byte[1024]
int num = fis.read(buf); // 一次性连续读取1024个字节,如果已快到文件末尾,那么可能也读不到1024个字节,它会通过返回一个整数来告诉调用者究竟读了几个字节
如果在最后一次读取后,再读,就返回-1
②一个专门用来读文本文件的封装工具:BufferedReader (里面嵌套了InputStreamReader(可以指定编码方式),InputStreamReader里面嵌套了字节流FileInputStream)
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(“d:/a.txt”),“UTF-8”));
String line = br.readLine(); //如果文件读完后还读,就返回 null
line = “”;
while( (line=br.readLine())!=null ){
System.out.println(line);
}
(2)然后是写文件(其实原理和上面的读文件一致)
① FileOutputStream(最底层字节流,针对所有的文件类型) 。对应write(),必须写入byte数组
FileOutputStream fos = new FileOutputStream("d:/test.txt",true);
String s = "a你好“;
byte[] bytes = s.getBytes("UTF-8"); // 将字符串按指定编码集编码--》将信息转成二进制数
fos.write(bytes); // 这样写入的数据,会将文件中的原数据覆盖
fos.close();
②BufferedWriter (字符流,只针对文本文件,里面嵌套OutputStreamWriter(可以指定编码方式),OutputStreamWriter里面嵌套FileOutputStream(最底层字节流))
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:/x.txt",true),"UTF-8"));
bw.write("我爱你,祖国\n"); // \r\n 在windows中是默认的换行符 而linux中默认的换行符:\n
bw.write("我爱你,contry");
bw.close();
2.对象的序列化
序列化其实就是将对象以特定的结构与规则,二进制与其他类型相互转换的过程。
一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
什么情况下需要序列化 1. 当你想把的内存中的对象写入到硬盘的时候。 2. 当你想用套接字在网络上传送对象的时候。3. 当你想通过RMI传输对象的时候。
其实也不需要想那么多,只要涉及,一些对象的读写,就在该对象类后面加上 implements Serializable。如下:
public class Product implements Serializable
{
private String ID;
private String name;
private float price;
3.可以从文件中任何位置开始读数据的工具:RandomAccessFile
// 可以从文件中任何位置开始读数据的工具:RandomAccessFile
RandomAccessFile raf = new RandomAccessFile("d:/p.dat", "r");
// 读id为2的那个商品的数据
long pos = id*28;
// 让raf的读取位置跳到指定的pos位置
raf.seek(pos);
// 然后开始读数据即可
// 先读4个字节返回一个整数
int pId = raf.readInt();
// 再读20个字节
byte[] b = new byte[20];
int read = raf.read(b);
// 然后将这20个字节转成字符串,但是尾部有大量空格
String string = new String(b);
// 去掉首尾的空格
String name = string.trim();
// 再读价格
float price = raf.readFloat();
raf.close();
之所以可以直接读出来返回int、float、string,是因为文件中本身的填写顺序和读出的顺序是一致的,有严格的规范,以int类型写入在0到3的位置,占用四个字节,读取时就要在相同的位置以相同的类型读出,其他类型同理。