--------------------android培训、java培训、期待与您交流! --------------------
................IO(Input Output)流
// IO是用来处理设备之间的数据传输。 java对数据的操作是通过流的方式。 Java用于操作流的对象都在IO包中。
流安操作数据分为两种:字节流与字符流。 流安流向分为:输入流和输出流。
//IO 常用基类
字节流的抽象基类: InputStream , OutputStream
字符流的抽象基类: Reader , Writer
//由这四个类派生出来的子类对象都是以父类名作为子类名的后缀。
InputStream ---> 子类 FileInputStream
Reader ---> FileReader
1.0.........FileWriter
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
FileWriter fw = new File Writer("demo.txt");//其实该步就是在明确数据要存放的目的地。
fw.write("dfdf");//调用write方法,将字符串写入到流中。
fw.flush();//该步将刷新对象中的缓冲数据到目的地中。
fw.close();//关闭数据流,但是在关前会刷新数据到目的地中。
//和 flush 区别,flush 刷新后,流可以继续使用。close 刷新后,会将流关闭。
2.0.....IOException
FileWriter f = null;//因下面finally要关闭流,为避免找不到对象 f,所以先在外面定义。
try{
f = new FileWriter("a.txt");// 23行
f.write("dfdjfk");
}
catch (IOException e)
{}//为简化编译,该处先不写处理内容。
finally{
try{
if(f!=null)//如果上面 23 行抛出异常,下面的关闭语句将出现找不到对象错误,
//所以要在此处判断一下对象是否存在。
f.close();//因该处会抛异常,所以写在 try 内。
}
catch (IOException e)
{} //简单的IO异常处理机制就写好了。
2.1.文件的续写
在创建对象的时候, FileWriter f = new FileWriter("a.txt",true);//该处重载方法支持 boolean 来决定是否覆盖。
传入 true 就是表示有该文件的话,就不覆盖。并在数据结尾处 .Write 数据。
//如没有则创建文件。
f.write("dd\r\ndd"); //如要换行写数据,要用 \r\n 。单用\n的h话,windows的记事本不支持。
2.2.文本读取方式 1
FileReader fr = new FileReader("a.txt");//和FileWriter 一样,只是和他反着,是读取流。
//创建一个文件读取流,和指定的文件名关联。要保证该文件已存在,否则会出 FileNotFoundException (文件找不到)异常。
fr.read();//调用读取流对象的read方法, 返回值为 int 型。
read();一次只读一个字符,而且会自动往下读。如到文件结尾,则返回 -1 。
2.3.文本读取方式 2
//.read(字符数组):read还可以接受一个字符数组。返回的是读到的个数 int 型。
char[] buf = new char[1024];//定义一个字符数组,用于存储读到的字符。
int num = 0; //建议数组大小定位 1024 的倍数。
while((num=fr.read(buf))!=-1)//如果值不为-1即为 true,则继续循环。
{
System.out.println(new String(buf,0,num));//String 还可以接受角标位,打印从第几位到第几位。
}
3.0..字符流的缓冲区
//缓冲区提高了对数据的读写效率。
对应类: BufferedWriter BufferedReader
// 缓冲区要结合流才可以使用。 在流的基础上对流的功能进行了增强。
FileWriter fw = new FileWriter("a.txt");//在创建缓冲区之前,必须要先有流。
BufferedWriter bufw = new BufferedWriter(fw);
//需要将被提高效率的流对象作为参数传递给缓冲区的构造函数。
bufw.close();//关闭缓冲区就会关闭流------》所以不用再写 fw.close(); 了。
bufw.newLine();//缓冲区提供的跨平台的换行符。
\r\n 用于windows 平台 \n 用于linux 平台 ,如同newLine 的话它自己会选择相应平台。
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);//同写入流一样,只是同他相反。
String s = bufr.readLine();//读一行,缓冲区特有方法。如到结尾,则返回 null。
bufr.close();
3.1..装饰设计模式
// 当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。
// 那么自定义的该类就称为装饰类。
装饰类通常会通过构造方法接受被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。
就像 BufferedReader(); 就装饰了 FileReader();
// 装饰和继承的区别
1. 装饰模式比继承要灵活,避免了继承体系臃肿。而且降低了类与类之间的关系。
2.装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能。
So ,装饰类和被装饰类通常是都属于一个体系中的。
3.2....LineNumberReader
带行号的读取。 属 BufferedReader 的子类。
4.0....字节流
InputStream -->读 OutputStream -->写
FileInputStream FileOutputStream
//同字符流操作方式一样。 FileInputStream fis = new FileInputStream("fis.txt");
fis.available(); 可以获取要操作的文件的的大小(有多少个字节)。
byte[] buf = new byte[fis.available()];//定义一个刚好文件大小的缓冲区,不再用循环了。
fis.read(buf);
S.op(new String(by));
这里面定义的 byte 数组长度为 .available() ,是因为这样读出的数据和接受数据的数组大小一样,正好可以
装下所有数据,因此不用再 while 遍历读取了,可以全部存下,然后打印。
如果用【1024】大小的数组的话,不用遍历,会将全部 1024 个字符打印出去,包括没有字符的空数组。
必须要用 while 和 -1 来判断读取全部有用字符。
4.1.字节流的缓冲区
new BufferedInputStream(new FileInputStream("a.txt"));
new BufferedOutputStream(new FileOutputStream("a_copy.txt"));
//和字符流的用法基本一样。
4.2.读取键盘录入
System.out :对应的是标准输出设备,控制台。
System.in :对应的标准输入设备,键盘。
InputStream in = System.in;//in接收键盘输入,返回的是InputStream 类型的字节流。
int by = in.read(); //用字节流的读取方法,读出输入的内容。 为 int 型。
S.op((char)by); //把 int 型强转回 char 类型。
4.3.转换流
键盘录入要涉及到录入一行并打印,要涉及判断 /r /n ,否则将是一个一个字符打印,所以就是读一行的原理。
而readLine()方法是字符流 BufferedReader 类中的方法,键盘录入的read方法是字节流 InputStream 方法。
这时,就要使用 字节流 和 字符流 转换的方法。
InputStreamReader 是字节流通向字符流的桥梁。 //都是对应的。InputStream 对应 Reader ,OutputStream 对应 Writer
OutputStreamWriter 字符通向字节流的桥梁。
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in()));//键盘输入的常见写法。
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while ((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
4.4.流操作规律
// 由于流对象过多,而不清楚要使用哪一个。所以要有三个明确:
三个明确: 1. 明确源和目的。 源 :输入流: InputStream Reader
目的:输出流: OutputStream Writer
2. 操作的是否为纯文本。 是: 字符流
// 不是: 字节流
3. 体系明确后,再明确要使用哪个具体的对象。
通过设备来进行区分: 源设备: 内存,硬盘,键盘。
目的设备: 内存,硬盘,控制台。
如果,
存储时,要加入指定编码表 utf-8 ,只有转换流可以指定编码表,就要用 OutputStreamWriter
而转换流对象需要接受一个字节输出流,而且是可以操作文件的字节输出流 FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
BufferedWriter bufw = new BufferedWriter(osw);
//如果不指定编码,转换流默认的是 GBK 编码。
还可以改变标准输入输出设备。
System.setIn(new FileInputStream("a.txt"));
System.setOut(new PrintStream("b.txt"));
4.5.异常日志信息
log4j;
5.0.......................................File 类
// 用来将文件或者文件夹封装成对象。 方便对文件与文件夹的属性信息进行操作。
// File 对象可以作为参数传递给流的构造函数。
File 类常见方法
1.创建 boolean createNewFile();//在指定位置创建文件,如果已存在,则不创建。返回 false.
//和输出流不一样,输出流对象一创建文件,如果以存在,将会覆盖。
boolean mkdir(); //创建文件夹
boolean mkdirs();//创建多级文件夹
2.删除 boolean delete();//删除失败返回false,如果文件正在被使用,则删除不了,返回 false.
void deleteOnExit();//在程序退出时,删除指定文件。
3.判断 boolean exists(); //文件是否存在。
isFile();// 是否为文件
isDirectory();//是否为目录
isHidden();// 是否是隐藏文件
isAbsolute();// 是否为绝对路径
4.获取信息 getName();// 获取名字
getPath();// 获取路径
getParent();// 获取父目录,对象创建时没有写明父目录的话(相对路径),返回为 null
getAbsolutePath();// 获取绝对路径
long lastModified();// 最后一次修改时间
long length();// 获取文件大小
5.1.....File 类--文件列表
File f = new File("c:\\a.txt");
String[] names = f.list();//调用list方法的file对象必须是封装了一个目录,该目录还必须存在。
for (String name: names)//list 方法是返回所在目录的列表。该列表是一个字符数组,所以用String接受。
{ //后用 forecho 来遍历输出。
S.op(name);
}
File[] files = File.listRoots();//获取到本机所有根目录(盘符)。
递归:
列出指定目录下文件或者文件夹,包含子目录中的内容。就是列出指定目录下所有内容。
因为目录中还有目录,只要使用同一个列出目录功能的函数即可。
// 如列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。
这种表现形式,或者变成手法,称为递归。
递归注意:
1.限定条件。
2.要注意递归的次数,尽量避免内存溢出。
public static void show(File dir){
File[] files = dir.listFiles();
for (int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
show(files[x]);
S.op(files[x]);
}
5.2.Properties 类
Properties 是hashtable 的子类。
也就是说他具备 Map 集合的特点,而且他里面存储的键值对都是字符串。是集合中和 IO 技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。
那么在加载数据时,需要数据有固定格式: 键 = 值。
继承至 Hashtable ,是 Map 集合的一种。用 setProperty(); 方法可以直接设置键和值。用 getProperty(); 方法通过键获得值。
本类 1.6 新加入方法 stringPropertyNames(); 可以返回 String 类型的 Set 集合,获取所有键。在用 getProperty() 方法
获取对应的值即可。
Properties 可以从配置文件中读取数据。定义一个文件读取字节流,并关联响应配置文件。用 load(你定义的读取流); 方法。
用 list(); 可以获取取出的存入 Properties 中的键值数据。
用 store(FileOutputStream); 可以将改动保存到文件中。要 new 输出流并关联要保存的文件。
5.3.打印流
// 该流提供了打印方法,可以将各种数据类型的数据都按原样打出。
PrintStream 构造函数可以接受的参数类型: 1. file对象 , File
2. 字符串路径。 String
3. 字节输出流。 OutputStream
PrintWriter 构造函数可以接受的参数类型: 1, file对象, File
2, 字符串路径, String
3, 字节输出流, OutputStream
4, 字符输出流, Writer
5.4.SequenceInputStream 合并流
//可以将多个流合并成一个流,既是合并文件。
SequenceInputStream 构造函数可以接收,两个 InputStream 流,或一个 InputStream 对象的 Enumeration 参数。
//将这两个流合并成一个流,或将 Enumeration 的元素合并成一个文件。
'只有 Vector 集合有获得 Enumeration 方法,Enumeration 是老的枚举,jdk 1.0 版本,已过时,不再使用。
Vector<FileInputStream> vector = new Vector<FileInputStream>();
//因只有 Vector 有该方法,定义一个 Vector 集合。
vector.add(new FileInputStream("first.txt"));//泛型限制只接受 FileInputStream 流对象。
vector.add(new FileInputStream("second.txt"));
//为 Vector 添加两个本地文件。
Enumeration<FileInputStream> enumeration = vector.elements();
//调用 Vector 的方法生成 Enumeration 对象。
SequenceInputStream sequenceInputStream = new SequenceInputStream(enumeration);
//将 Enumeration 传递给 SequenceInputStream 。
FileOutputStream fileOutputStream = new FileOutputStream("third.txt");
//定义输出流,接收合并后的文件。
int len = 0; byte[] buf = new byte[1024];
//字节流读取方法。
while((len=sequenceInputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,len);
}
fileOutputStream.close();
sequenceInputStream.close();
5.5.切割流
5.6.操作对象 ---对象的序列化
ObjectInputStream
ObjectOutputStream
// 被操作的对象要实现 serializable
ObjectOutputStream oos =
new ObjectOutputStream(new FileOutputStream("某个类.object"));
oos.writeObject('某个类');
oos.close();
//可以将对象持久化存储。但该对象要实现 serializable 接口,该接口称为 标记接口 ,没有任何方法需要去覆盖。
//该接口会使对象序列化,序列化方法由各成员变量决定,如成员有改变,则序列化ID 也会改变。
想要某个成员不被序列化,可在前加入 transient 修饰符,另,静态成员不会被序列化。
5.7.管道流
PipedInputStream
PipedOutputStream
//一般数据读取,需先存入数组中,在对数组进行操作,使用该类的话,可同时对数据进行操作。所以容易造成死锁,
需用多线程技术,分开线程调用该输入流和输出流。
// 两管道流间用输入流的 .connect(输出流); 来进行接通。
6.随机访问流
RandomAccessFile
该类是 Object 的子类,但是他是 IO包中的成员,因为他具备读和写功能。内部封装了一个数组,而且通过指针对数组
对数组的元素进行操作。可以通过 getFilePointer 获取指针位置,同时可以通过 seek 改变指针的位置。
//其实完成读写的原理就是内部封装了字节输入流和输出流。
通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读 r ,读写 rw 。
如果模式为只读 r ,不会创建文件,回去读取一个已存在的文件。如果该文件不存在,则会出现异常。
如果模式为 rw ,操作的文件不存在,会自动创建。如果存在则不会覆盖。
6.1.....操作基本数据类型的留对象
DataOutputStream DataInputStream
//该流对象可以直接操作基本数据类型
DataOutputStream 中的 writeInt(); writeBooleam(); writeDouble(); writeLong();
writeUTF(); //等....
//直接按响应格式写入,不用转换。
6.2.....ByteArrayInputStream
操作字节数组 ByteArrayInputStream 和 ByteArrayOutputStream
操作字符数组 CharArrayReader 和 CharArrayWriter
操作字符串 StringReader 和 StringWriter
ByteArrayInputStream, 在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream, 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是
//数据目的地。
//因为这两个六队西哪个都操作的数组,并没有使用系统资源,所以,不用关闭流。
6.3..字符编码
'字符流的出现是为了方便操作字符。 更重要的是加入了编码转换。
通过子类转换流来完成 : InputStreamReader
OutputStreamWriter
//在两个对象进行构造的时候可以加入字符集。
'编码表的由来
计算机只能识别二进制数据,早期由来是电信号。
为了方便应用计算机,让他可以识别各个国家的文字。
就将各个国家的文字用数字来表示,并一一对应,形成一张表。//就是编码表。
ASCII -- 美国标准信息交换吗,用一个字节的7位可以表示。
ISO8859-1 - 拉丁码表。 欧洲码表。用一个字节的8位表示。
GB2312 - 中国的中文编码表。
GBK - 中国的中文编码表升级,融合了更多的中文字符号。
Unicode - 国际标准码,融合了多种文字。所有文字都用两个字节来表示,Java 语言使用的就是 UNICODE
UTF-8 - 最多用三个字节来表示一个字符。
--------------------android培训、java培训、期待与您交流! --------------------