------- android培训、java培训、期待与您交流! ----------
IO
Input Output
IO流用来处理设备之间的数据传输
Java对数据的操作是通过流的方式
Java用于操作流的对象都在IO包中
流按操作数据分为两种:字节流与字符流。
流按流向分为:输入流,输出流。
输入流和输出流的流向的理解?
流就是处理数据的一种方式或者一种手段,或者理解为一种数据流。 以内存为中心从硬盘已有的数据读取出来放内存里面的这个过程就是输入流。 把内存中的数据存储到硬盘中的这个过程就是输出流。
什么时候使用流对象?
操作设备上的数据或操作文件的时候可以使用。 字符流
字符流的抽象基类:Reader , Writer。 字符流的理解,由来和作用?
由于很多国家的文字融入进来,比如说中文在编码表中默认占2个字节。而为了按照文字的单位来处理,所以出现了字符流。 由来:早期的字节流+编码表,为了更便于操作文字数据。 作用:为了处理文字数据。
操作设备上的数据或操作文件的时候可以使用IO流。
字符流的抽象基类:Reader , Writer。
字符流的理解,由来和作用?
由来:早期的字节流+编码表,为了更便于操作文字数据。
作用:为了处理文字数据。
复制文件的原理和代码。
原理:
首先用一个读取流对象和一个文件进行关联,然后用一个写入流对象作为目地的,为了把读取流中的文件传输到目的地流对象中,我们就提供了一个字符数组,
为了关联这个数组,所以读取流对象有一个read()方法与这个字符数组进行关联,
同理,写入流对象也有一个write()方法与这个字符数组进行关联,这样2个流对象就相连接了,而这个字符数组就相当于一个中转站。
/*
* 对文本文件进行复制。将c盘的文件复制到d盘中。
* 原理:其实就是一个最简单的读写过程。
* 从c盘源,读取数据,并将读到的数据,写入到目的d盘中。
*/
public class CopyTextFileTest {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
//1,创建一个字符读取流读取与源数据相关联。
fr = new FileReader("demo.txt");
//2,创建一个存储数据的目的地。
fw = new FileWriter("copyDemo.txt");
//3,创建一个字符数组将读取流对象和写入流对象相连接。
char[] buf = new char[1024];
//4,每次读取的长度不一样,所以定义一个变量.
int len = 0;
//5,用循环读取文件中的数据
while((len= fr.read(buf)) != -1) //判断是否读取完没
fw.write(buf,0,len); //为了只读取有效的数据
} catch (Exception e) {
}finally{
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
读取字符流对象的两种方式
第一种读取方式 一次读一个字符
//1,创建一个文件读取流对象,和指定名称的文件相关联
//2,要保证该文件时已经存在的。如果不存在,会发生异常。FileNotFoundException
FileReader fr = new FileReader("Demo.txt");
//3,调用读取流的方法,read方法一次读一个字符,而且会自动往下读。
int line=0; //read返回时int型的数,即返回的是字符的ascII表对应的数字
while ((line=fr.read())!=-1)
{
sop((char)ch);
}
第二种读取方式 把字符读到buf数据中
//1,创建一个文件读取流对象,和指定名称的文件相关联
//2,要保证该文件时已经存在的。如果不存在,会发生异常。FileNotFoundException
FileReader fr = new FileReader("Demo.txt"); //把Demo.txt中的数据读到控制台
//3,定义一个字符数组,用于存储独到的字符该read(char[]) //返回的是读到字符的个数
char[] buf = new char[1024];
int len=0;
while((len=fr.read(buf))!=-1) //把读到的字符暂时存到buf数组中
{
sop("num="+num+"...."+new String(buf,0,len));
}
缓冲区的基本思想?提高效率的原理。
缓冲区的基本思想就是对要处理的数据进行临时存储。譬如购物车以及篮子。
给读取流对象和写入流对象提供中转站。
BufferedReader ,BufferedWriter.高效的体现
内部将数组进行封装。变成对象后,方便于对缓冲区的操作。提高效率。并提供了对文本便捷操作的方法。
readLine()和newLine()
自定义缓冲区,MyBufferedReader
* 模拟一个缓冲区
* 基于已有的缓冲区思想,我们可以从源读取用read方法。
* 我们的缓冲区,应该是一个更高效的read读取方法。
* 按照文本特点,提供一个特有的操作文本的方法。
* 一次读取一行文本,只要是到行结束符之前的文本即可。
* @return 返回读取到的一行文本
* @throws IOException
* 原理:
* 就是从缓冲区中取出数据,并存储到一个临时容器中。
* 如果取到了回车符,就将临时容器中的数据转成字符串返回。
*/
public String myReadLine() throws IOException{
//1,定义一个临时容器,进行临时存储
StringBuilder sb = new StringBuilder();
//2,定义一个变量,接收读取到的字符,也就是转成ask码表后的一个int型数字
int ch = 0;
while((ch = myRead()) != -1){
//3,当读取到\r时,直接跳出本次循环
if(ch == '\r')
continue;
//4,当读取到\n时,直接跳出当前循环
if(ch == '\n')
return sb.toString();
//5,当都没有读取到时,就将这些数据存储到临时容器中。
sb.append((char)ch);
}
//6,当临时容器中的长度不等于0时,就输出字符。
if(sb.length() != 0)
return sb.toString();
return null;
}
public void close() throws IOException {
}
public int read(char[] arg0, int arg1, int arg2) throws IOException {
return 0;
}
}
readLine
方法的原理。
就是从缓冲区中获取数据,并进行临时存储,直到读取到了换行符,将临时存储的数据转成字符串返回。它对于操作文本是毕竟方便,可以完成一行一行的读取文本。
装饰设计模式,以及和继承的区别?
对原有类进行了功能的改变,增强。
区别:
继承在对对象进行增强时,采用的是子类覆盖父类中的写方法,
且这些子类使用的功能的原理都一样,这样就显得很臃肿。
而BufferWriter的出现避免了继承体系关系的臃肿,比继承更为灵活。
在为了增强功能的情况下,相较于继承,BufferWriter这种方式解决起来更为方便。
使用字符流可以复制图片吗?为什么?
不能,因为字符流就是字节流+编码表,而用字符流去复制图片时,字符流会默认将图片的字节码格式进行编码,
所以会导致复制后的图片与原图片可能不一致。
字符流继承体系简图
字节流的抽象基类:InputStream ,OutputStream。
字节流的基本应用?复制MP3的例子。
</pre><p><pre name="code" class="java">public class CopyMediaFileTest {
public static void main(String[] args) throws IOException {
copy_3();
}
private static void copy_3() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\4.mp3");
int ch = 0;
while((ch=fis.read())!=-1){
fos.write(ch);
}
fos.close();
fis.close();
}
private static void copy_2() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\3.mp3");
BufferedInputStream bufis = new BufferedInputStream(fis);
BufferedOutputStream bufos = new BufferedOutputStream(fos);
int ch = 0;
while((ch=bufis.read())!=-1){
bufos.write(ch);
}
bufos.close();
bufis.close();
}
}
private static void copy_1() throws IOException {
FileInputStream fis = new FileInputStream("c:\\0.mp3");
FileOutputStream fos = new FileOutputStream("c:\\1.mp3");
byte[] buf = new byte[1024*4];//自定义缓冲区4兆
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
fis.close();
}
}
字节流继承体系简图
转换流InputStreamReader,OutputStreamWriter
转换流的由来?
为了方便于字符流与字节流进行转换,也就是建立一个桥梁。建立桥梁后,它就将字节流和编码表进行了封装,实现了对字符的便捷操作。另外也为了方便字符流与字节流之间的操作。
转换流的应用?
字节流中的数据都是字符时,转成字符流操作更高效。
转换流的两个桥梁都是从哪里到哪里?
首先将文件通过InputStreamReader的方式将字节数据转成字符,为了高效,将其先存储到缓冲区中。
然后通过OutputStreamWriter将缓冲区中的字符数据转成字节,最后输出。
转换流的另一个功能,编码的体现?
流的基本应用小节
流是用来处理数据的。处理数据时,一定要先明确数据源,与数据目的地。
数据源可以是文件,可以是键盘。
数据目的地可以是文件、显示器或者其他设备。
而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理.转换处理等
IO流的操作规律总结:
1,明确体系:
数据源:InputStream ,Reader
目的地:OutputStream,Writer
2,明确数据:因为数据分两种:字节,字符。
数据源:是否是纯文本数据呢?
是:Reader
否:InputStream
目的地:
是:Writer
否:OutputStream
到这里就可以明确具体要使用哪一个体系了。
剩下的就是要明确使用这个体系中的哪个对象。
3,明确设备:
数据源:
键盘:System.in
硬盘:FileXXX
内存:数组。
网络:socket
数据汇:
控制台:System.out
硬盘:FileXXX
内存:数组
网络:socket
4,明确额外功能:
1,需要转换?是,使用转换流。InputStreamReader OutputStreamWriter
2,需要高效?是,使用缓冲区。Buffered
1, 复制一个文本文件。
1,明确设备:
源:硬盘上的一个文件。 FileReader
目的:硬盘上的一个文件。FileWriter
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
2,需要额外功能吗?
需要,高效,使用buffer
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
2, 读取键盘录入,将数据存储到一个文件中。
InputStream in = System.in;
FileWriter fw = new FileWriter("a.txt");
4,需要额外功能吗?
需要,因为源明确的体系时Reader。可是源的设备是System.in。
所以为了方便于操作文本数据,将源转成字符流。需要转换流。InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
FileWriter fw = new FileWriter("a.txt");
需要高效不?需要。Buffer
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new FileWriter("a.txt"));
3, 读取一个文本文件,将数据展现在控制台上。
需要额外功能?
因为源是文本数据,确定是Writer体系。所以为了方便操作字符数据,
需要使用字符流,但是目的又是一个字节输出流。
需要一个转换流,OutputStreamWriter
FileReader fr = new FileReader("a.txt");
OutputStreamWriter osw = new OutputStreamWriter(System.out);
需要高效吗?需要。
BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
4, 读取键盘录入,将数据展现在控制台上。
BufferedReader bufr =new BufferedReader(new InputStreamReader(Systme.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
5, 读取一个文本文件,将文件按照指定的编码表UTF-8进行存储,保存到另一个文件中。
1,明确设备:
源:硬盘:FileReader.
目的:硬盘:FileWriter
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
File类
File类的作用
1,用来将文件或者文件夹封装成对象
2,方便对文件与文件夹的属性信息进行操作。
3,File对象可以作为参数传递给流的构造函数。
File对象基本使用。了解创建,删除,获取,判断等。
创建:
boolean createNewFile():创建一个新的空文件,不过该文件已存在,就不会创建
boolean mkdir():创建指定的目录
boolean mkdirs():创建指定的目录以及父目录
删除:
boolean delete():删除文件或目录
void deleteOnExit():虚拟机结束时,会自动删除指定的文件或目录
获取:
String getAbsolutePath():绝对路径
String getPath():相对路径
String getParent():返回此路径名父目录的路径,如果没有则返回null
String getName():返回此路径名表示的文件或目录的名称
long length():返回此路径名表示的文件的长度
long lastModified():返回此文件最后一次被修改的时间
判断:
boolean exists():判断此路径名表示的文件或目录是否存在
boolean isFile():判断此路径名表示的文件或目录是否是一个标准的文件
boolean isDirectory():判断此路径名表示的文件或目录是否是一个目录
import java.io.*;
class filedemo1
{
public static void main(String[] args) throws IOException
{
method1();
}
public static void method1()throws IOException
{
File f1 = new File("file1.txt");
File f2 = new File("文件夹\\第二个\\第三个\\第四个\\第五个");
//f2.mkdir();//创建文件夹,只能创建一级目录
f2.mkdirs();//创建多级文件夹
System.out.println("create:"+f1.createNewFile());
System.out.println("exists"+f1.exists());//判断存在必须先创建文件
}
}
File
对象的过滤器。
实现FilenameFilter接口,然后覆盖其accept方法并指定需要过滤的扩展名就。实现此接口的类实例可用于过滤器文件名。
boolean accpet(File dir, String name):当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false。
递归
递归就是函数自身直接或间接调用自身。
当一个功能被重复使用,而且使用过程中,参数运算的数据不断的在发生着变化。
这时可以使用递归这种手法来解决问题。
注意事项:
1,必须要定义条件,否则会出现栈内存溢出。
2,要控制递归的次数。
Properties类
Properties类的作用?
主要用于存储键值的map集合中Hashtable的子类。
操作配置文件最方便的对象。
Properties的特点?
1,它没有泛型。
2,它里面的键和值都是固定的类型,字符串。
3,它自己有特有的存储和取出的动作。
4,它有和IO流相关联的方法。
5,它经常用于简单配置文件的解析。
IO中的其他功能流对象:
1,打印流:PrintStream:
特点:
1,构造函数可接收File对象,字符串路径,字节输出流。意味着打印目的可以有很多。
2,该对象具备特有的方法 打印方法print println,可以打印任何类型的数据。
3,特有的print方法可以保持任意类型的数据表现形式的原样性,将数据输出到目的地。
而对于OutputStream父类中的write方法,是将数据的最低字节写出去。
PrintWriter:
1,当操作的数据是字符时,可以选择PrintWriter,比PrintStream要方便。
2,它的构造函数可以接收File对象,字符串路径,字节输出流,字符输出流。
3,构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该true对println方法有效。
什么时候用?
当需要保证数据表现的原样性时,就可以使用打印流的打印方法来完成,这样更为方便。
保证数据表现形式的原样性的原理:其实就是将数据变成字符串,再进行写入操作。
print(int)和 write(int)的区别?
print(int)方法可以保持任意类型的数据表现形式的原样性,将数据输出到目的地。
write(int)方法只是将数据的最低字节写出去。
PrintWriter在什么情况下可以自动刷新?
构造函数中,如果参数是输出流,那么可以通过指定另一个参数true完成自动刷新,该true对println方法有效。
序列流:SequenceInputStream:
特点:
1,将多个字节读取流合并成一个读取流,将多个源合并成一个源,操作起来更方便。
2,需要的枚举接口可以通过Collections.enumeration(collection);
文件切割的原理?
通过读取流关联源文件,然后读取流将一个临时的数据进行了一个临时的缓冲,然后通过这个临时的缓冲区将数据分散到不同的文件当中。
也就意味着一个读取流对应着多个输出流。
管道流:
特点:
1,可以将管道输出流连接到管道输入流通信管道。
2,需要和多线程技术相结合的流对象。
编码表的由来
l 计算机只能识别二进制数据,早期由来是电信号。
l 为了方便应用计算机,让它可以识别各个国家的文字。
l 就将各个国家的文字用数字来表示,并一一对应,形成一张表。
l 这就是编码表。
常见的码表有哪些,都有什么特点?
ASCll:美国标准信息交换码
用一个字节的7位可以表示
ISO8859-1:拉丁码表。欧洲码表
用一个字节的8位表示
GB2312:中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字字符号。
Unicode:国际标准码,融合了多种文字。
所有文字都用两个字节来表示,Java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符