------- android培训、java培训、期待与您交流! ----------
Java中的IO:
Java中的IO流分为两种,即字节流和字符流
字节流有两个基类:InputStream 和 OutputStream
字符流有两个基类:Writer 和 Reader
现在我们通过字节流来复制一个mp3文件:(没次读取并写入一个字符)
impor java.io.*;
classStreamDemo { public static void main(String[]args) { FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3"); FileOutputStream fo=new FileOutputStream("C:"+File.separator+"2.mp3");
int ch=0; while((ch=fi.read())!=-1) { fo.write(ch); } fi.close(); fo.close(); } } |
也可以定义一个字节数组作为中专站:
import java.io.*;
class StreamDemo { public static void main(String[]args) { FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3"); FileOutputStream fo=newFileOutputStream("C:"+File.separator+"2.mp3");
byte[] buf=new byte[1024]; int len=0; while((len=fi.read(buf))!=-1) { fo.write(buf,0,len); } fi.close(); fo.close(); } } |
importjava.io.*;
classStreamDemo { public static void main(String[]args) { FileInputStream fi=newFileInputStream("C:"+File.separator+"1.mp3"); FileOutputStream fo=newFileOutputStream("C:"+File.separator+"2.mp3");
BufferedInputStream bufr=newBufferedInputStream(fi); BufferedOutputStream bufw=newBufferedOutputStream(fo);
byte[] buf=new byte[1024]; int len=0; while((len=bufr.read(buf))!=-1) { bufw.write(buf,0,len); } bufr.close(); bufw.close(); } } |
如果要操作的是字符文件,我们就用FileWriter和FileReader对文件的读取和写入与上面的字节流类似
File类:
File类是在java的IO操作中常用的一个类,
用来将文件或者文件夹封装成对象,
方便对文件和文件夹进行操作,
File对象可以作为参数传递给流的构造函数,
在File类中有很多常用的方法。
importjava.io.*; classFileDemo { public static void main(String[]args) { //File类的构造函数的演示: File f1=new File("a.txt"); File f2=newFile("C:\\abc","b.txt");
File f3=newFile("C:\\abc"); File f4=newFile(f3,"c.txt");
File f4=new File("C:"+File.separator+"abc"+File.separator+"r.txt"); } } |
File类中的常用的方法:
创建文件夹:mkdir() 只能创建一级目录。mkdirs()创建多级目录。
创建文件:createNewFile();
删除:delete(); deleteOnExit()在程序退出时删除文件
判断:exists()判断文件是否存在 isFile()判断是否是文件 isDirectory()判断是否是目录
现在我们看一个File操作的例子(理解递归的思想)
importjava.io.*; classFileDemo3 { public static void main(String[]args) { File dir=new File("E:\\test"); showDir(dir); }
public static void showDir(File dir) { System.out.println(dir); File[] files=new dir.listFiles(); for(int x=0;x<dir.length;x++) { if(files[x].isDirectory()) { show(files[x]); } else System.out.println(files[x]); } } } |
字符编码的问题:
在Java中,字符只以一种编码形式存在
但“在Java中”到底是指在哪里呢?就是指在JVM中,在内存中,在你的代码里声明的每一个char,String类型的变量中。
JVM的这种约定使得一个字符存在的世界分为了两部分:JVM内部和OS的文件系统。在JVM内部,统一使用UTF-16表示,
当这个字符被从JVM内部移到外部(即保存为文件系统中的一个文件的内容时),就进行了编码转换。
因此可以说,所有的编码转换就只发生在边界的地方,JVM和OS的交界处,也就是你的各种输入输出流(或者Reader,Writer类)起作用的地方。
尽管看上去混乱繁杂,但是所有的IO基本上可以分为两大阵营:面向字符的Reader啊Wrtier啊,以及面向字节的InputStream啊OutputStream啊。
下面我来逐一分解,其实一点也不难。
面向字符和面向字节中的所谓“面向”什么,是指这些类在处理输入输出的时候,在哪个意义上保持一致。如果面向字节,那么这类工作要保证系统
中的文件二进制内容和读入JVM内部的二进制内容要一致。不能变换任何0和1的顺序
这种输入输出方式很适合读入视频文件或者音频文件,或者任何不需要做变换的文件内容。
而面向字符的IO是指希望系统中的文件的字符和读入内存的“字符”(注意和字节的区别)要一致。例如我们的中文版WindowsXP系统上有
一个GBK的文本文件,其中有一个“汉”字,这个字的GBK编码是0xBABA(而UTF-16编码是0x6C49),当我们使用面向字符的IO把它读入内存
并保存在一个char型变量中时,我希望IO系统不要傻傻的直接把0xBABA放到这个char型变量中,我甚至都不关心这个char型变量具体的二进
制内容到底是多少,我只希望这个字符读进来之后仍然是“汉”这个字。从这个意义上也可以看出,面向字符的IO类,也就是Reader和Writer类,
实际上隐式的为我们做了编码转换,在输出时,将内存中的UTF-16编码。字符使用系统默认的编码方式进行了编码,而在输入时,将文件系统中已经编
码过的字符使用默认编码方案进行了还原。我两次提到“默认”,是说
Reader和Writer的聪明也仅此而已了,它们只会使用这个默认的编码来做转换,你不能为一个Reader或者Writer指定转换时使用的编码。这也意味着,
如果你使用中文版WindowsXP系统,而上面存放了一个UTF-8编码的文件,当你使用Reader类来读入的时候,它会傻傻的使用GBK来做转换,转换后的
内容当然驴唇不对马嘴!
这种笨,有时候其实是一种傻瓜式的功能提供方式,对大多数初级用户(以及不需要跨平台的高级用户)来说反而是件好事。
但我们不一样啦,我们都是国家栋梁,肩负着赶英超美的责任,必须师夷长技以治夷,所以我们总还要和GBK编码以外的文件打交道。
说了上面这些内容,想必聪明的读者已经看出来,所谓编码转换就是一个字符与字节之间的转换,因此Java的IO系统中能够指定转换编码的地方,
也就在字符与字节转换的地方,那就是:InputSteamReader和OutputStreamWriter!
------- android培训、java培训、期待与您交流! ----------