java基础--笔记18

来源:互联网 发布:剑三喵姐妖娆捏脸数据 编辑:程序博客网 时间:2024/06/06 10:43

盘符路径在书写时,要注意不同系统中不同。
在windows系统,java表示盘符是用\\表示。或File.separator表示。

绝对路径 getAbsolutePath 文件存储的位置
相对路径 相对于当前项目而言
getPath() file对象中封装的路径是什么就获取什么。
创建多级目录  mkdirs()
删除目录必须保证该目录是空目录,记住删除目录必须是从里往外删。

记住:在获取目录中的内容时,返回的结果很可能是很多文件和文件夹,则应该由一个容器去接受。

list() 和listFile()区别:
list()获取到的是指定目录下当前的文件和文件夹的名称。
liatFile()获取到的是指定目录下当前文件和文件夹File对象,可以进一步对文件和文件夹进行操作。

递归:函数自身调用自身,当一个功能被重复使用,但是每次功能运行参数都不同。
注意:
1,递归必须定义条件
2,控制递归的次数 

注意在书写函数的时候一定要留意if else 判断语句的书写,符合条件的代码要书写在各自的代码块中。

FileFilter 和 FilenameFilter 区别
FileFilter的主要作用就是检测文件是否存在。FileFilter 和它的前身FilenameFilter 的唯一不同是FileFilter使文件作为一个文件对象,而FilenameFilter使文件作为一个目录和一个字符串名被过滤。

输出流会自动创建文件,如果该文件存在,则覆盖(删除,新建)。

在写入文件时,如果想换行写入,可以在写入文件的前面加入换行符,在windows中,换行符是由两个字符组成\r\n ,但是这样在开发中扩展性不强,只能在windows中使用。由此我们可以想到当初学File时,定义的分隔符静态字段,可以通过获取系统中的属性信息来完成换行,定义方法:
private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 

InputStream中available()方法,可以用在创建缓冲区时使用,用来确定缓冲区数组的长度,但是要慎用,因为如果关联的文件很大的话,很容易发生堆内存溢出,所以,最好定义缓冲区时还是1024的整数倍。

注意: 关闭流时,后开的流先关闭。

flush刷新 和 close关闭 的区别
flush刷新后,流还存在,可以继续写入数据。
close关闭后,不能执行读写操作了。

IO技术在处理数据时,因为数据量较大,需要通过缓冲技术提高效率。缓冲区是用于临时存储数据的。
java中提供了相应的具备缓冲功能的对象。BufferedInputStream 和BufferedOutputStream。如果需要对缓冲区数据进行别的操作,用到这个java提供的缓冲区对象的方法时,可以用这个缓冲区,否则,自己定义缓冲区即可实现。

解码和编码
生活中的数字 ---> 数字 : 编码
数字 ---> 生活中的数字 : 解码

String ---> byte [] : 编码
byte [] ---> String : 解码

编码表:生活中文字和二进制之间的对应关系。
1,ASCII : 美国标准信息交换码。特点:一个字节中的后七位就可以表示所有的文字了。最高位0,也就是说该码表中的文字对应的都是正数。

2,ISO8859-1 : Latin拉丁码表,特点:兼容ASCII,并使用了一个字节中的八位,而且最高位为1 ,所有的文字对应负数。

3,GB2312 : 中国的编码表,6763个中文和符号,特点:两个字节表示一个中文。每一个字节开头都是-1,也就是说两个字节对应的都是负数。

4,GBK :目前应用码表。两万多,特点:在原有GB2312基础上,两个字节标识一个中文,固定第一个字节是负数,第二个字节可以是整数也可以是负数。

5,GB18030 : 升级的中文码表,但是还没有普及使用。

6,Unicode : 国际标准码。所有的文字都用两个字节表示。java语言对于字符char使用的是该码表。java的String类型使用本地系统默认码表。简体中文版的电脑:默认GBK。

7,UTF-8 : Unicode转换格式的码表,Uniicode码表有一个问题:浪费。UTF-8:能用一个字节存储的就用一个字节存储,存不下,就用两个字节,再存不下,三个字节。每一个字节开头都有标识位,可以很清晰知道这是UTF-8.解析很方便。
一个字节存储 : 0XXXXXXX
二个字节存储 : 110XXXXX   10XXXXXX
三个字节存储 : 1110XXXX   10XXXXXX   10XXXXXX

开发中最常见的码表:GBK  UTF-8    ISO8859-1

字节流:可以操作所有的数据,使用字节数组。
InputStream     OutputStream

InputStream:用于读取(输入)字节的流对象超类。
|--FileInputStream:用于读取文件。
|--FilterInputStream
|--BufferedInputStream:提高了读取的效率。
OutputStream:用于写入(输出)字节的流对象超类。
|--FileOutputStream:用于写入文件。
|--FilterOutputStream
|--BufferedOutputStream:提高写入的效率。

字符流:专门用于操作字符数据。字节流+编码表 使用的都是字符数组
Reader : 用于独处字符流的抽象类
Writer :写入字符流的抽象类
Reader:用于读取字符流的抽象类
|--InputStreamReader
|--FileReader
Writer:写入字符流的抽象类。
|--OutputStreamWriter
|--FileWriter

OutputStreamWriter :字符通向字节的桥梁,可以指定码表。不指定就是默认码表,实现的是编码功能。
InputStreamReader : 字节通向字符的桥梁,可以指定码表。不指定就是默认码表,实现的是解码功能。

FileReader 和 FileWriter :字节流 + 默认码表

转换流:实现字节和字符之间的转换操作。
OutputStreamWriter 和InputStreamReader :字节流+指定码表

操作文本数据,一般使用字节流。如果操作文件中的文本数据需要使用FileReader 和FileWriter 。如果操作文本数据时,需要使用编解码,需要使用OutputStreamWriter 和InputStreamReader。

想要将一个文本文件转换成其他码表存储,在读取这个文本文件时,一定要采用编码时的码表读取,再按指定的码表编码,否则会出现乱码。

为什么从文本文件中读取出来的中文字符转成字节时,显示的全是正数?
byte [] buf = new byte[1024];
int = isr.read(buf);
也就是说为什么得到的是int型,0-255。
是因为系统显示时将原中文的字节码byte提升为了int类型,在提升的同时,本应该是11111111 11111111 11111111 1xxxxxxx 替换成了00000000 00000000 00000000 1xxxxxxx 所以得到是一个0-255这件的数。但是底层的二进制数据没有被破坏,还是原来的数据。
(要获取文件的字节码,一定要用字节流操作数据)

关于按字节截取中英文混杂字符串,半个中文舍弃
其核心问题是如何判断半个中文,那就需要先知道中文的编码特点,现在默认的是GBK编码方式,也就是一个中文字符是由两个字节组成,前一个字节为负,后一个字节可以为正也可以为负。而
英文编码方式为ASCII,由一个字节组成,为正。所以只要判断字节为正负即可,但是问题是遇到截取的是中文的第二个字节(负)列?要是为负数,但不能舍弃。
这时就需要判断怎样才是整个中文的字节。一个中文是两个字节,所以只要截取位之前连续出现的负数为偶数个,就不舍,是奇数个就舍弃最后那个字节。 

乱码问题解决
编码错了,是无法解码的,没救。
要是编码对了,解码错了,有可能有救。
要是编码是GBK,解码用的是ISO8859-1,只需将解出来的码,用ISO8859-1重新编码,再用GBK解码即可。
但要是用的是UTF-8解码,没救。
因为ISO8859-1是拉丁码,不支持中文,没有破坏源码。而UTF-8支持中文,但是好GBK的编码方式不同,用GBK编的码,在UTF-8中要是找不到对应的中文就会用-17 ,-65 , -67 来表示,已经换了源码。

联通问题
“联通” 问题,主要是由于中文联通的GBK编码值和UTF-8编码特征相符,当文件中,全是符合UTF-8的编码方式时,记事本在打开的时候,是一个解码过程,这个时候,由于文件权符合UTF-8编码方式,就会按照UTF-8的码表去解码,所以造成了乱码。

字符输入流缓冲区BufferedReader :实现字符,数组,行的高效读取。

记住:当用输出流输出数据时,目的地没有数据出现,可能是数据在内存中,需要刷新一下。

properties 用到输入流时,关联的文件必须是键值关系相对应的文件。

切割,合并问题
切割:如果切割文本文件,可以使用字节流也可以使用字符流。但是如果切割的不是文本文件,如MP3,avi,doc等文件时,就必须使用字节流来切割。
切割时,可以根据需要切割的数量和切割的大小来切割。
在设置缓冲区时,一般设置1M或者2M,当切割每个子文件很大时,可以通过循环读取缓冲区写入文件中,来达到要求。
合并:合并时要注意碎片文档信息的读取,如果碎片文档信息是用properties写的,就要用properties来读取。获取碎片文件个数后要判断是否和文档信息里的一致。读取完碎片后,可以先将碎片文件关联输入流,将输入流对象存入list集合。合并有两种方式,可以选择直接用字节输入流将list集合中的碎片遍历写入一个文件。也可以通过collections工具获取到list的枚举接口,再将枚举对象传给sequenceinputstream,用里面的读取方法读取。

 PrintWriter:向文本输出流打印对象的格式化表示形式。

 PrintStream:为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。目的可以是文件,流,字符串路径。打印方法不抛出异常。

问题1:
用字节输出流在文件中写入97数字,打开记事本看到却是a?
是因为将97这个数字的字节写入到了文件中,记事本在读取解析时,解码97--->a

问题2 :
write方法在做什么事情?
97是几个字节? 4个字节,int类型
write方法只将最后一个字节写入到文件中(文档描述中有)。

System.out 这个流的目的是显示器。通常这个流在系统启动时就已经存在了,操作这个流时可以不用关闭,一旦关闭,输出语句就全用不了了。
System.in这个流的源是键盘。

ObjectOutputStream和 ObjectInputStream
ObjectOutputStream对象的序列化
ObjectInputStream对象的反序列化
序列化:其实就是将对象写入到流中。对象按照有序的排序进行存储。
Serializable 如果一个类要序列化,必须实现这个接口,为了得到版本序列化。
在序列化时,类中的静态,瞬态(被transient修饰)不能存储。
序列化时最好显示声明serialVersionUID。这样类中的对象改变内容时,就不会再修改serialVersionUID,而不会导致再次调用时抛出异常。

装饰设计模式:
比继承更为灵活。它不和每一个具体子类对象关联。却可以提高所有子类的功能。

注意:装饰类和被装饰的具体类没有必然联系,但他们却有相同的功能,只不过装饰类的功能可以被被装饰类进行额外(功能)职责的添加。意味着:装饰类和被装饰类是所属于同一个体系的。
如果想要给一个体系中的成员们添加额外功能,直接使用装饰模式就可以完成。

IO体系的组成。

File

InputStream
|--FileInputStream:可以读取文本的字节输入流
|--FilterInputStream
|--BufferedInputStream:给输入流添加缓冲区,高效
|--DataInputStream:可以从底层输入流中读取基本数据类型
|--ObjectInputStream:对象的反序列化
|--ByteArrayInputStream:内部提供一个字节数组缓冲区的输入流
|--SequenceInputStream:实现输入流的序列化

OutputStream
|--FileOutputStream:将数据写入文本中
|--FilterOutputStream
|--BufferedOutputStream:提供一个输出缓冲区
|--DataOutputStream:数据输出流,输出基本数据类型
|--PrintStream:打印流,打印数据值表现形式
|--ObjectOutputStream:对象的序列化,实现暂时的持久化存储
|--ByteArrayOutputStream:数据写入一个byte数组,可以通过toByteArray()和toString()获取数组中数据。


Reader
|--InputStreamReader:字节转成字符,可以设置解码方式。
|--FileReader:读取文本的字符流
|--BufferedReader:字符输入流缓冲区,可以从字符输入流中读取文本,缓冲各个字符,高效,readLine
|--CharArrayReader:字符输入流的字符缓冲区
|--StringReader:源为字符串的字符流
Writer
|--OutputStreamWriter:字符转成字节,可以设置编码方式。
|--FileWriter:写入文本文件的字符输出流
|--BufferedWriter:将文本写入字符输出流,缓冲各个字符,高效
|--CharArrayWriter:自动增长的字符输出缓冲区。可以通过toByteArray()和toString()获取数组中数据。
|--StringWriter:可以用其回收在字符串缓冲区中的输出来构造字符串。
|--PrintWriter:向文本输出流打印对象的格式化表示形式。

RandomAccessFile:支持对随机访问文件的读取和写入

IO流规律总结
对需求进行分析,需求中只要有操作设备上数据动作,就需要使用IO技术。
明确一:明确需求中的源和目的
     源:能操作源的体系:InputStream  Reader
     目的: OutputStream  Writer
     先分体系

明确二:涉及的数据是否是文本数据,并且有对文本数据的操作
     是:
               源:Reader
               目的:Writer
     不是
               源:InputStream
               目的:OutputStream
               使用哪个具体的体系就明确了

明确三:明确数据所在的设备
     源设备:
               硬盘:File开头
               键盘:System.in
               内存:数组,ByteArray  CharArray  String
               网络:socket

     目的设备:
               硬盘:File开头
               键盘:System.out
               内存:数组,ByteArray  CharArray  String
               网络:socket
     注意:System操作的数据是字节数据

明确四:需要额外功能不?
     需要!
               需要将源的字节转成字符。InputStreamReader
               高效 ,加入缓冲区
               
总结:
     额外功能:
     1,高效:Buffered
     2,转换,编码解码:字节-->字符 InputStreamReader
                                    字符-->字节 OutputStreamWriter
     3,保证输出的数据的表现形式:打印流
     4,多个读取流合并成一个读取流:序列流SequenceInputStream
     5,想要将对象直接序列化和反序列化:ObjectOutputStream
                                                              ObjectInputStream
     6,直接操作基本类型的数据读写:DataInputStream
                                                        DataOutputStream
     7,随机访问文件:不用再想源和目的 直接RandomAccessFile


在复制文本文件时,如果仅作复制动作,不需要考虑数据是字节还是字符。直接使用字节流就好了。但是如果在赋值过程中,需要对文本中的字符数据进行操作,必须使用字符流。
0 0
原创粉丝点击