现在的位置: 首页 > 综合 > 正文

第十七天:IO流

2018年05月17日 ⁄ 综合 ⁄ 共 4451字 ⁄ 字号 评论关闭

Week 04

day16
一. 要点
1. java.io.File
用于表示文件(目录);只用于表示文件(目录)
的信息(名称,大小等)不能对文件的内容进行访问
2. java.io.File基本API

File(String)
long length() //这个方法十分重要,如果是目录返回值不一定,如果是文件则返回文件内容有多个字节
long lastModified() 上次修改时间
String getName()
String getPath()//将此抽象路径名转换为一个路径名字符串,是一个相对路径。
boolean exists()
boolean dir.isFile()
boolean dir.isDirectory()
boolean mkdir()
boolean mkdirs()
boolean delete();
boolean createNewFile() throw IOException  File file2 = new File("test") file2.createNewFile();
File[] listFile()//返回该目录下的所有文件和目录

3. 回调模式和FileFilter
File[] listFile(FileFilter)

回调概念:(十分重要,在java中android开发中十分常见)
它的运行顺序是这样的,
File[] listFiles = file.listFiles(new FileFilter() {

@Override
public boolean accept(File pathname) {
System.out.println("in accept():"+
         pathname.getName());//跟踪代码
return pathname.getName().endsWith(".java");
}
});
里面的先创建出来,然后送给listFiles,也就是告诉listFiles,我有,你什么时间用来调用我就行了,
然后在执行listFiles的时间,再去调用里面的方法。这就回调。


但是
String list();返回的是一个字符串数组。
在File中基本是迭代出现的,一个返回file数组,一个返回string数组 。


4. java.io.RandomAccessFile
可以访问(读/写)一个文件中任意位置的字节信息
下面两个参数是,这类的构造函数。
// arg0 要访问的文件
// arg1 访问的模式 "r" 只读模式,"rw" 读写模式
RandomAccessFile(File, String) 
  throws FileNotFoundException
RAF 维护一个指针,指向要读写的位置 ,//这是的游标指向的就是第一个,与iterator不一样(指向第一个之前)。
指针会随着读写自动后移
int read()//返回的就是char类型的
void write(int)//写在当前指针位置一个字节,并且指针下移一位。
seek(long pos)//pos - 从文件开头以字节为单位测量的偏移量位置,在该位置设置文件指针。
long getFilePointer()//,得到指针在哪一个位置,指针最初指在第一个字符上,且为0,注意与iterator不同
//iterator最初是指在第一个之前,值为-1.
//到此文件开头的偏移量(以字节为单位),在该位置发生下一个读取或写入操作。 



预备知识:
字符类型:char, 字符类型是一个16位无符号整数!
  所以字符类型是一个整数 。
   a 字符类型的值是对应字符的编码, 是unicode(十分重要)
     编码. Java支持国际化.
     英文部分的值与ascII(128个)编码一致.
     char是定长编码, 所有的字符都是16位.

什么叫编码?
为了实现对字符信息的存储,人们将可能用到的字符排成一个有序的字符队列,
这种由多个有序字符组成的集合称为“字符集-Charset”,而在计算机中世纪保存的是字符在字符集中的序号,
即一个二进制形式的整数。而到底采用1个还是多个字节以及具体如何来存储一个字符集的字符,
这种相关的规定被称为“编码-Encoding”。


我多年来一直不理解的东西,为什么read()返回是一个int,而int只在0-255之间
我们知道 int有32位,但是read()的返回值是它相应的ascII编码值,我们知道,它只有128个,
而ascII,主要用在英文和西欧的地区的文字 ,无法用中文,可以自己把这些字符打印出来看下。
然而,char类型是16位的无符号整数,它字符类型的值是对应字符的编码是unicode16,可以理解为
是对ascII的补充,所以它们英文部分是完全相同的,例如:A不论是在ASCII编码还是UNICODE编码中
都是65.所以经过,read()返回的代码值虽然是对应的ascII编码,但是英文部分又与char对应的编码相同
所以用char转型时,仍然能够显示出来,中文肯定不行了。

所以说read()不加参数只能按照一个字节一个字节(8位)去读取。

而且raf.read()执行完以后会移动到下一个字符上,所以如果你还是用这个操作操作的就是下一个,恐怕不是
你想要的那个。要注意。

它是存储在int 32位中的低八位。


然后把它转成无符号的int类型,
//"ABCDEABCDEABCDEABCDE" 
    //  ^
    // 00000000 00000000 00000000 0100 0001 = 41


/**

* @param filename
* @throws IOException
* 把某个文件中的大写字母变成小写
*/
public static void lowcase(String filename) throws IOException{
File file = new File(filename);
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
int pos = 0;

while (pos<file.length()) {
int b = randomAccessFile.read();//读取完成后,指针指向一个。
if (b>='A'&&b<='Z') {//也就是说,b此时是大写字母
b = b-('A'-'a');//转换为小写字母
//因为前面往后移动一位,所以此时要往前移动,否则就把字母的位置写错了。
randomAccessFile.seek(randomAccessFile.getFilePointer()-1);
randomAccessFile.write(b);//写成功后,往后移动一位。
}
//读取更改完一个字节后,加1
pos++;
}
randomAccessFile.close();
}


// 读取尽可能多的字节,填充作为参数的字节数组
int read(byte[])//把数据写到缓冲区。
write(byte[], int off, int len)//把缓冲区的数据写出来

这个两个逼方法我也明白了。
首先:为了提高效率,我们不再用上面那个方法一个一个字节的读,一个一个字节的取,
而是先把它读取到一个大的缓冲区,read(byte[])返回的就是读取了几个字节,
如:byte[] b = new byte[5];则表示一次读取五个字节到缓冲区,但是我们知道
如果这个文章的字节数字不能正好被5整除,那么最后一次读取的返回值就会《=5
最后,如果由于已到达文件的末尾而不再有数据,则返回 -1。 
而如果我们想要得到那个每次读取的数据,应该到缓冲区里面去找,即 b.把这个数组打印出来
就知道里面有数据了。

byte[] b = new byte[1024];即缓冲区大小 为1M。


write的方法是把你读取到缓冲区里面的数据写到指定位置,
参数:
b - 缓冲区数据。
off - 从缓冲区哪个数据开始读取
len - 其实是一个缓冲区数据的终结,读取到哪。
[off,len]其实就是b里面从第几个字节开始,到第几个字节结束,
还是那个样子包含前面不包含后面。

注意RandomAccessFile这个类在read write seek时间都会造成游标的移动。

为什么read()返回-1.
//  读取文件的一个byte无符号填充到 int的低八位
    //返回值: 0x000000ff ~ 0x00000000
    按照这样计算,int不可能为负数 的。但是只是sun规定,如果读取完毕,它就是-1.
    //如果读到文件尾, 返回-1

byte[] buf= new byte[10];
    //count 是读取的数据个数: 1~10 >0, 如果-1到文件尾
    int count;


5. 
java.io.InputStream  输入流
java.io.OutputStream 输出流
//上面两个类都是抽象类。
所以。InputStream inputStream = new FileInputStream("demo.txt");

java.io.InputStream
直接已知子类: 
AudioInputStream, ByteArrayInputStream, FileInputStream, 
FilterInputStream, InputStream, ObjectInputStream, 
PipedInputStream, SequenceInputStream, StringBufferInputStream 


所谓流,形象的说法,就是自己不动,文件一个一个字节的从面前流过。

java.io.FileInputStream(File)    FIS
java.io.FileOutputStream(File)   FOS

java.io.BufferedInputStream(InputStream)  BIS
java.io.BufferedOutputStream(OutputStream) BOS


BufferedInputStream(InputStream in) 
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 
BufferedInputStream(InputStream in, int size) 
          创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 

//它是把一大块读取出来,然后让你一个一个的read()去读 ,选取这一大块读取完成后,它会再去读取一大块,
//然后再让你一个一个的读取,而这个大块的缓冲区是让java去维护的。

中:unicode编码是4e2d.
GB2312是GBK的一部分。

out.write("这样也可以".getBytes("GBK"));
否则这样out.write(0xd6);//中(GBK/GB2312)  
让你很崩溃。

二. 练习
查找一个目录(包括其子目录)下所有指定扩展名的文件
把一个BMP文件变色

颜色是32位,RGB分别占八位 FFFFFF
每一种最大是255 ,然后用255-读取到已经有的颜色,


 

抱歉!评论已关闭.