----------------------class="Apple-converted-space">?android开发、java培训、期待与您交流! ----------------------
转换流
?转换流是字符流与字节流之间的桥梁,是为了方便字符流与字节流之间的操作。
?当字节流中都是字符时,转成字符流操作更为高效,
?例如:能不能使用readLine方法完成键盘录入的一行数据的读取呢,但是readLine是BufferedReader的方法,
?
?而System.in是InputStream的方法,这样就用到了转换流(InputStreamReader)
?InputStreamReader是一个字符流,要想转换字节流那就要在
构造函数的时候把字节流当参数传入
?读取转换流
?
?BfferedReader bufr =
?
??
?new BufferedReader(new InputStreamReader(System.in));
?写入转换流:字符转字节,比如录入的是字符,把它存到
硬盘上是字节
?
?BufferedWriter bufw =
?
??
?new BufferedWriter(new OutputStreamWriter(System.out));
?
转换流规律:
?操作流的时候流对象有很多该用哪个呢?通过三个明确来完成。
?1.明确源和目的 ?有的时候可能只有源或目的,要先明确
?
?源:因为是源所以使用读取流,即 InputStream ,Reader
?
?目的: 写入流 即 OutputStream , Writer
?2.明确操作的数据是否为纯文本 ?即是明确用字节流还是字符流
?
?是:用字符流
?
?不是:用字节流
?3.明确
设备 ?就是明确用那个对象,就是看用不用转换流
?
?源设备:
内存 ,硬盘 ,键盘
?
?目的设备:内存 ,硬盘,控制台
?
?然后再确定下需不需要提高效率,就是确定需不需要缓冲流。
?例如:
?1,将一个文本文件中数据存储到另一个文件中。复制文件。
?
?这个明确了源和目的都有,
?
?源:InputStream ?Reader
?
?是纯文本吗?是。明所以用字符流 就是Reader
?
?源设备:硬盘 ?不需要转换流
?
?这时候就可以确定了用 FileReader
?
?是否需要提高效率?是。加入缓冲区 BufferedReader、
?
?FileReader fr = new FileReader("Demo.txt");
?
?BufferedReader bfr ?= new BufferedReader(fr);
?
?目的:OutputStream ?
??Writer
?
?是纯文本吗?是。所以用字符流 Writer.
?
?目的设备:硬盘 ?不需要转换流。
?
?所以就可以确定用 FileWriter了。
?
?是否需要提高效率?是。加入缓冲区 BufferedWriter
?
?FileWriter fw = new FileWriter();
?
?BufferedWriter bfw = new BufferedWriter(fw);
?2,需求:将键盘录入的数据保存到一个文件中。
??
?
?明确1这个既有源也有目的
?
?源: InputStream ?
?Reader
?
?是否为纯文本?是,键盘录入的也是字符,用Reader
?
?源设备:键盘。对应的对象是 System.in。这时就想了上面不是明确了用Reader了吗,但是
?
?System.in是字节流啊,所以既然明确了用Reader这时就需要用转换流了InputStreamReader。
?
?需要提高效率吗?需要。所以要用BufferedReader。
?
?InputStreamReader isr = new InputStreamReader(System.in);
?
?BufferedReader bfr = new BufferedReader(isr);
?
?目的:OutputStream ?
?Writer
?
?是否为纯文本?是, 用Writer
?
?目的设备:一个文件文件 在硬盘 不需要转换流,可以确定用FileWriter
?
?FileWriter fw = new FileWriter("Demo.txt");
?
?需要提高效率吗?需要。
?
?BufferedWriter bufw = new BufferedWriter(fw);
--------------------------------------------------------------------------------------------
?
?扩展:想要把录入的数据按照指定的
编码表(utf-8),将数据存到文件中。
?
?源和上面的一样,不变。
?
?目的:OutputStream ?Writer
?
?是否为纯文本?是,Writer
?
?目的设备:硬盘 一个文件 ?用 FileWriter
?
?FileWriter是按默认的编码(GBK)存的。但是要求按照指定的编码(utf-8)存数据
?
?而指定编码表只有转换流能制定,所以使用的对象是OutputStreamWriter,而转换流
?
?又要接收一个字节流,而且该字节流还能操作文件,所以就是 FileOutputStream
?
?需要提高效率吗?需要。所以要用到BufferedReader
?
?OutputStreamWriter osw =?
?
??
?new OutputStreamWriter(new FileOutputStream("Demo.txt"),"UTF-8");
?
?所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,
?
?需要用到转换流。
?改变标准输入输出流设备:
?
?系统默认的标准输入输出设备是 System.in 和 System.out
?
?但是可以通过System类中setIn,setOut方法对默认设备进行改变。
?
?System.setIn(new FileInputStream(“1.txt”));//将源改成文件1.txt。
?
?System.setOut(new FileOutputStream(“2.txt”));//将目的改成文件2.txt
---------------------------------------------------------------------------------------------------------------------------------
?
File类
?流在操作的只有数据,而数据最明显的体现形式就是文件,文件又包含了很多的属性和行为信息,
?比如说前缀名、扩展名、文件自己的大小时间等,所以文件是一个复杂的事物而这个事物有很多,
?所以java就对文件这类的事物进行了描述,也把它封装成了对象,方面了我们对文件或文件夹的
?属性进行操作。而File类的对象也主要用来
获取文件本身的一些信息,如文件大小权限等,不涉
?及对文件的读写操作。
?查看API知道java提供了三种创建方法来生成一个文件对象。
?(1)根据参数指定的文件路径创建一个File文件对象,就是把某个文件封装成对象
?
?File file1 ?= new File("D:\\abc\\123.txt");
?(2)根据给定的目录创建一个File实体对象,其中"d:\\abc"为目录,"123.txt"为文件的名称
?
?File file2 ?= new File("D:\\abc","123.txt");
?(3)可以根据已知的目录文件对象File创建一个新的File实体对象
?
?File d = new File("D:\\abc");
?
?File file3 = new File(d,"123.txt");
?File类所提供的方法中,有的是针对文件的处理,有的是针对目录的处理,可以通过一些方法来
?判断文件是否存在以及文件的相对路径和绝对路径等,File类的常见方法有:
?1,创建。
?
?boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
?
??
??
?和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
?
?boolean mkdir():创建目录文件夹。
?
?boolean mkdirs():创建多级文件夹。
?2,删除。
?
?boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
?
?void deleteOnExit();在程序退出时删除指定文件。
?3,判断。
?
?boolean exists() :文件是否存在.
?
?isFile(): 是否为文件
?
?isDirectory();是否为目录
?
?isHidden();
?
?isAbsolute();
?4,获取信息。
?
?getName()://获取
文件名
?
?getPath()://获取相对路径
?
?getParent()://返回的绝对路径的文件父目录
?
?getAbsolutePath() //获取绝对路径
?
?long lastModified()?
?
?long length()?
?部分代码:
?
?
class FileDemo
{
public static void main(String[] args) throws IOException
{
File f = new File("abc.txt");//把文件封装成对象
sop(f.createNewFile());//创建一个文件创建成功返回true,如果已存在创建不成功,返回false
File f = new File("abc");
sop(f.mkdir());//创建一个目录,mkdirs能创建多级目录
//在判断文件对象是否是文件或者目录时,一定要先判断该文件对象封装的内容是否存在
isexists();//因为封装了一个文件对象,如果没创建的话,系统里就没有的所以要先判断下。
isFile();//判断你创建的是否为文件
isDirectory();//判断是否为目录
File f = new File("abc\\abc.txt");
getParent();//获取绝对路径的文件父目录,你创建时是相对路径会返回null
//如果相对路径中有上一层目录那么该目录就是返回结果。如上返回父目录abc
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
?文件列表:
?listRoots();//能列出我们机器里面有效的盘符,它是一个
静态方法,返回的是File数组
?String[] list();//返回
值类型是是String数组,
?File f = new File("d:\\");
?Stringp[] names = f.list();//打印的是d盘下所有文件和文件夹的名称,所以返回的是
字符串数组
?
??
??
??//但是要确定调用list方法的File对象必须是封装了一个目录,并且该目录还必须存在 ?
?for(String name : names)//不然你封装了一个文件对象,那它返回的数组就为null,那就不能遍历数组了
?{
?
?System.out.println(name);
?}
?File[]
files = f.listFile();
?for(String file : files)
?{
?
?System.out.println(file.getName()+"::"+file.length());//因为返回的是文件对象仍然能调用方法
?}
----------------------------------------------------------------------------------------------------------------------------------?
?
递归:在遍历文件夹的时候,遍历的结果中仍有文件夹,这事是不是还要在遍历一次啊,比如说,你打开d盘
?
??里面是不是有很多文件夹啊,然后是不是就要点开看看啊,然后里面还有文件夹是不是还要打开?这
?
??样是不是在重复一个操作,就是遍历文件夹里的元素,里面有文件夹的话就再遍历....这样我们在
?
??
写代码的时候是不是再重复用同一个方法,就是用一个方法遍历文件夹,如果里面有文件夹的话,就在
?
??调用本方法。也就是函数自身调用自身。这种编程手法就是递归。
?
??部分代码:
?
??
?
?
class FileDemo
{
public static void main(String[] args) throws IOException
{
File dir = new File("f:\\javademo");
showDir(dir);
}
public static void showDir(File dir)
{
File[] files = dir.listFiles();
for(int x=0; x
{
if(files[x].isDirectory())//判断,如果便利中碰到文件夹
showDir(files[x]);//就再调用此方法进行遍历
else
System.out.println(files[x]);
}
}
}
??
?递归要注意:
?
?1,限定条件。没条件限定的话,函数里面又调用它自身不就相当于死
循环啦。
?
?2,要注意递归的次数。尽量避免内存溢出。每次递归都会在栈内存中开辟空间,不限定的话会内存溢出
------------------------------------------------------------------------------------------------------------------------------------?
?
Properties类:
?Properties是
hashtable的子类。一个可以将键值进行持久化存储的对象。
?也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。
?是集合中和IO技术相
结合的集合容器。
?
?该对象的特点:可以用于键值对形式的配置文件。
?那么在加载数据时,需要数据有固定格式:键=值。
?特点:
?1:可以持久化存储数据。
?2:键值都是字符串。
?3:一般用于配置文件。
?
??|-- load():将流中的数据加载进集合。
? 原理:其实就是将读取流和指定文件相关联,并读取一行数据,因为数据是规则的key=value,所以获
?
?取一行后,通过 = 对该行数据进行切割,左边就是键,右边就是值,将键、值存储到properties集合中。
? |-- store():写入各个项后,刷新输出流。
? |-- list():将集合的键值数据列出到指定的目的地。
--------------------------------------------------------------------------------------------------------------------------------
?
IO包中的其他类:
?打印流?
?
?PrintWriter与PrintStream 可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类
?
?型的数据都原样打印。
?
?字节打印流:PrintStream ?
?
??构造函数可以接收的参数类型:
?
??1,file对象。File
?
??2,字符串路径。String
?
??3,字节输出流。OutputStream
?
?字符打印流:PrintWriter
?
??构造函数可以接收的参数类型:
?
??1,file对象。File
?
??2,字符串路径。String
?
??3,字节输出流。OutputStream
?
??4,字符输出流,Writer。
-----------------------------------------------------------------------------------------------------------------------------------
?序列流 ?
?
?SequenceInputStream 对多个流进行合并。它的构造函数接收的是两个输入流,或者是接收一个输
?
??入流的
枚举。
?
?比如说要把三个文件的内容复制到另一个文件中,是不是要一个一个的重复Copy文件的那个动作啊,
?
?就是每复制一个文件都要创建一个写入流和输出流,然后再进行读写操作,复制三个文件是不是就
?
?要重复三次啊,并且创建目的文件的时候还要写成可续写格式,不然就会被覆盖掉,而序列流就解
?
?决了这个问题,他可以把多个流合并在一起,然后再进行其他操作。
??
?
?//把三个文件复制到另一个文件中 部分代码:
?
public static void main(String[] args) throws IOException
{
//枚举只有list集合里的vector有所以要创建一个集合来装输入流
Vector v = new Vector();
//把三个文件的读取流对象添加到集合里
v.add(new FileInputStream("d:\\1.txt"));
v.add(new FileInputStream("d:\\2.txt"));
v.add(new FileInputStream("d:\\3.txt"));
//获取集合的枚举Enumeration
Enumeration en = v.elements();
//将输入流的枚举传给序列流,之后操作这个流就行了
SequenceInputStream sis = new SequenceInputStream(en);
//创建一个写入流再然后进行频繁的读写就行了
FileOutputStream fos = new FileOutputStream("c:\\4.txt");
byte[] buf = new byte[1024];
int len =0;
while((len=sis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
能合并就能切割://切割一图片
public static void spilt() throws IOException
{
FileInputStream fis = new FileInputStream("E:\\0.PNG");
FileOutputStream fos = null;
byte[] arr = new byte[1024*1024];
int len = 0;
int x=1;
//每一次循环是不是都创建了一个流就是创建了一个文件啊?
while((len=fis.read(arr))!=-1)
{
fos=new FileOutputStream("E:\\spilte\\"+(x++)+".part");
fos.write(arr,0,len);
fos.close();
}
fis.close();
}
?------------------------------------------------------------------------------------------------------------------------------ ?
?
?操作对象的流
?
?ObjectInputStream与ObjectOutputStream 被操作的对象需要实现Serializable (标记
接口);
?
?流是可以操作数据的,现在数据被封装成对象了,我们知道对象是存放在堆内存中的,用完之后
?
?就成了垃圾了,一被清理之后这个对象是不是就不存在了?而现在讲的这个流就可以操作对象,
?
?把这个对象的数据存放在硬盘上,对象里都封装了一些数据,那这些数据是不是就随着对象也存到
?
?了硬盘上啦?这样的话即使这个程序结束了对象被清理了,我们是不是仍然能够获得这个对象里的
?
?数据啊,因为它已经被存放到硬盘上了。
?
?另外操作的那个对象的类要能被
序列化,某个类要想能被序列化,就得实现java.io.Serializable 接口。
?
?
?部分代码:
?
??ObjectOutputStream的目的是把对象和流相结合,是不是先把对先把流当参数传给它啊,所
?
??以ObjectOutputStream在构造函数时一定要接收个流,什么流呢?就是把对象怎么着的流?也
?
??就是目的。
?
??
?
??//既然要把对象写进文件那就要创建一个写入流
?
??FileOutputStream fos = new FileOutputStream("t.tmp");
?
??//把写入流当参数传给ObjectOutputStream
?
??ObjectOutputStream oos = new ObjectOutputStream(fos);
?
??//操作的这类person对象的类要实现Serializable接口
?
??oos.writeObject(new Person());//将指定对象写入ObjectOutputStream。
?
??oos.writeInt(12345);
?
??oos.close();
-----------------------------------------------------------------------------------------------------------------------------------------
?
?管道流
?
?PipedInputStream和PipedOutputStream输入输出可以直接进行连接,通过结合
线程使用。
?
?管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据
?
?由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。
?
?不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在
?
?缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,
?
?则认为该管道已损坏。?
?-------------------------------------------------------------------------------------------------------------------------------------
?
?RandomAccessFile类
?
?该类不是算是IO体系中子类。而是直接继承自Object。但是它是IO包中成员。因为它具备读和写
?
?功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获
?
?取指针位置,同时可以通过seek改变指针的位置。
?
?其实完成读写的原理就是内部封装了字节输入流和输出流。
?
?通过构造函数可以看出,该类只能操作文件。而且操作文件还有模式:只读r,,读写rw等。
?
?
?如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现
异常。
?
?如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
?
?java语言提供了一个RandomAccessFile类来处理对一部分文件的输入/输出。RandomAccessFile类
?
?创建的流于前面的输入输出流不一样,它既不是输入流InputStream的子类也不是输出流类OutputS-
?
?-tream的子类,但是RandomAccessFile类创建的流的指向既可以做为源也可以作为目的,换句话说
?
?如果相对一个文件进行读取操作时,可以创建一个指向该文件的RandomAccessFile流,这样既可以
?
?从这个流中读取文件的数据,也可以从这个流中写入数据到文件。
?
?可以用以下两种方式打开一个随机存取文件:
?字符编码
?
?字符流的出现为了方便操作字符。更重要是的加入了编码转换。
?
?通过子类转换流来完成。 InputStreamReader OutputStreamWriter
?
?在两个对象进行构造的时候可以加入字符 集。
?
?编码:字符串变成字节数组。
?
?解码:字节数组变成字符串。
?
?String-->byte[]; ?str.getBytes(charsetName);
?
?byte[] -->String: new String(byte[],charsetName);
?部分代码:
class EncodeDemo
{
public static void main(String[] args)throws Exception
{
String s = "哈哈";
byte[] b1 = s.getBytes("GBK");
System.out.println(Arrays.toString(b1));
String s1 = new String(b1,"utf-8");
System.out.println("s1="+s1);
//对s1进行iso8859-1编码。
byte[] b2 = s1.getBytes("utf-8");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2,"gbk");
System.out.println("s2="+s2);
}
}
?
----------------------?android开发、java培训、期待与您交流! ----------------------