JAVA IO 专题

来源:互联网 发布:微信营销软件 编辑:程序博客网 时间:2024/05/28 11:29

首先看一下常用的几种编码方式

public class EncodeDemo{public static void main(String[] agrs)throws IOException{String s="中国ABC";byte[] byte1=s.getBytes(); //默认采用项目的UTF-8编码byte[] byte2=s.getBytes("GBK");//显示指定编码方式为GBKbyte[] byte3=s.getBytes("UTF-16be"); for(byte b:byte1){/** * 把字节转换成int以十六进制的方式显示 * 默认采用项目的编码,此处使用UTF-8,得到的结果为e4 b8 ad e5 9b bd 41 42 43  *可见采用utf-8编码,中文占用三个字节,英文占用一个字节 */System.out.print(Integer.toHexString(b & 0xff)+" ");} System.out.println(); for(byte b:byte2){/** * 把字节转换成int以十六进制的方式显示,高位三个字节补0 * 显示指定编码方式为GBK,,得到的结果为d6 d0 b9 fa 41 42 43 * 可见采用GBK编码,中文占用三个字节,英文占用一个字节 */System.out.print(Integer.toHexString(b & 0xff)+" ");} System.out.println(); for(byte b:byte3){/** * java是双字节编码utf-16be * 把字节转换成int以十六进制的方式显示,高位三个字节补0 * 显示指定编码方式为UTF-16be,得到的结果为4e 2d 56 fd 0 41 0 42 0 43 * 可见采用UTF-16be编码,中文占用两个字节,英文也占用两个字节 */System.out.print(Integer.toHexString(b & 0xff)+" ");} System.out.println(); /*  * 字节数组转换成字符串,必须与之前的转换采用相同的编码方式,不然会出现乱码  */ String s1 = new String(byte1);  System.out.println(s1); //中国ABC,采用默认的项目编码格式 String s2 = new String(byte2); System.out.println(s2);//�й�  出现乱码,因为byte2用的是GBK编码,转换成字符串时用得默认的UTF-8 String s3 = new String(byte2,"GBK"); System.out.println(s3);//中国ABC ,显示指定GBK编码方式,便不会出现乱码}}

通过这个例子可以看出,常用的编码方式有UTF-8,汉字编码站三个字节,英文字母编码占用1个字节;GBK编码,中文占用两个字节,英文字母占用一个字节;java 是双字节UTF-16be编码,这种编码方式中文和英文都占用两个字节,在字符串与字节进行转换时,默认采用项目指定的编码方式,还要注意双向转换时,编码方式要相同,不然会出现乱码。


File类的使用

java.io.File类用于表示文件或目录,它只用于表示文件或目录的信息(名称,大小等),不能用于文件内容的访问

public class FileDemo {public static void main(String[] args){/* * 了解几种常用的构造函数 */File file = new File("F:\\开心");//注意:路径要使用双斜杠或者反斜杠System.out.println(file);File file2 = new File("F:\\开心","开心1.txt");File file3 = new File(file2,"开心2.txt");if(!file.exists()){/* * 如果目录不存在,则创建目录,mkdirs()可用于创建多级目录 * file.createNewFile()用于创建文件 */file.mkdir(); }else{file.delete();}/* * File类的几种常用API */System.out.println(file.isFile());System.out.println(file.isDirectory());System.out.println(file); //打印文件的路径System.out.println(file.getAbsolutePath());//同样打印文件的完整路径System.out.println(file.getName());//打印文件或目录的名字System.out.println(file.getParent());//打印文件或目录的父目录System.out.println(file.getParentFile());}}

以上介绍FIle类创建对象的几种方式以及常用API



包装对对文件或目录的几种常用操作,如过滤,遍历等

/<span style="font-family: Arial, Helvetica, sans-serif;">/包装File的一些常用操作,如过滤,遍历</span>
public class FileUtil{/* * 遍历目录下的所有文件和目录 */public static void listDirectory(File dir)throws IOException{if(!dir.exists()){throw new IllegalArgumentException("目录"+dir+"不存在");}if(!dir.isDirectory()){throw new IllegalArgumentException(dir+"不是目录");}/*String[] fileNames = dir.list(); //返回字符串数组,直接子的名称,不包含子目录下的内容for (String string : fileNames){System.out.println(string);}*/File[] files = dir.listFiles();if(files!=null && files.length>0){for (File file : files){System.out.println(file);if(file.isDirectory()) //递归遍历{listDirectory(file);}}}} }

RandomAccessFile:提供了对文件内容的访问,既可以读文件,也可以写文件。它提供对文件的随机访问,可以访问文件的任意位置

1>文件模式

    java文件,在硬盘上是byte byte byte...存储的,是数据的集合

2>打开文件

     打开文件有两种模式 “rw” 读写操作  “r”  只读操作

     RandomAccessFile  raf = new  RandomAccessFile  (file , "wr"),RandomAccessFile的随机访问是依靠文件指针实现的,打开文      件的默认指针位置prointer=0,即在文件的开头。读写操作会伴随着指针位置的移动。

3>写方法 

    raf.write(int), ----->只写一个字节,同时指针只想下一个位置,准备再次进行写操作

4>读方法

    raf.read()---->只写一个字节

5>文件读写完成后一定要关闭,不然会发生意想不到的错误

public class RandomAccessFileDemo {public static void main(String[] args)throws IOException{File file = new File("demo");if(!file.exists()){file.createNewFile();}RandomAccessFile raf = new RandomAccessFile(file, "rw");System.out.println(raf.getFilePointer()); //获取文件指针的位置,0raf.write('A');//只写入一个字节System.out.println(raf.getFilePointer()); //1int i = 0x7fffffff;//最大的整数//用write方法,每次只能写一个字节,写一个int需要写4次raf.write(i>>24);raf.write(i>>16);raf.write(i>>8);raf.write(i);//也可以直接写一个int,时机底层也是进行四次写操作raf.writeInt(i);System.out.println(raf.getFilePointer());String s="中国";byte[] byte1 = s.getBytes("gbk");raf.write(byte1);System.out.println(raf.length()); //文件的长度 13//读文件必须把文件指针移到文件的开始,也可以移到指定的位置进行读取raf.seek(0);byte[] buf = new byte[(int) raf.length()];raf.read(buf) ;//批量读取System.out.println(Arrays.toString(buf));//以十六进制的方式输出for (byte b : buf){System.out.print(Integer.toHexString(b&0xff)+" ");}raf.close();}}

IO流(输入流,输出流)

字节流

1>

InputStream 抽象了应用程序读取数据的方式,读到程序中为输入

OutputStream  抽象了应用程序写出数据的方式

2>

EOF =End 读到-1就读到了文件的结尾

3>输入流基本方法

int b = in.read(); 读取一个字节填充到int低八位

in.read(byte[] buf)  ; 批量读取字节到字节数组中

in.read(byte[] buf , int start ,int size)

4>输出流基本方法

out.write(int b) // 写出int b 的低八位到流

out.write(byte[] b) ; 写出字节数组中的全部字节

out.write(byte[] b , int start ,int size) //从下表start开始,写出size个字节

5>具体实现类  

FileInputStream --->具体实现了在文件中读取数据

/* * 读取指定文件内容,以十六进制输出到控制台 * 每读取10个字节换行, * 单字节读取,不适合大文件,效率很低 */public class IOUtil{public static void printHex(String filename)throws IOException{FileInputStream fis = new FileInputStream(filename);int b;int i=1;while((b=fis.read())!=-1) //每次只读取一个字节{if(b<=0xf)System.out.print("0"); //如果只有第四位,则在前面补零System.out.print(Integer.toHexString(b)+" ");if(i++%10 == 0){System.out.println();}}fis.close();}/* * 批量读取,大区大文件时效率很高 * 常用的文件读取方式 */public static void printHexByByteArray(String filename)throws IOException{FileInputStream fis = new FileInputStream(filename);byte[] buffer = new byte[10*1024];/* * 从fis中批量读取字节,放入到buf中,从第0个位置开始放,最多放buffer.length个字节 * 返回的是读取字节的个数 * 为了防止一次读不完一个文件,所以用到while循环,读到文件结尾为止 */int n;while((n=fis.read(buffer, 0, buffer.length))!=-1){int k=1;for (int i=0;i<n;i++){if(buffer[i]<=0xf)System.out.print("0");System.out.print(Integer.toHexString(buffer[i]&0xff)+" ");if(k++%10 == 0)System.out.println();}}System.out.println();fis.close();}/* * 文件的copy */public static void  copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists())throw new IllegalArgumentException("原文件"+srcFile+"不存在");if(!srcFile.isFile())throw new IllegalArgumentException(srcFile+"不是文件");FileInputStream in = new FileInputStream(srcFile);FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[10*1024];int n;while((n=in.read(buf, 0, buf.length))!=-1){out.write(buf, 0, n);}}


FileOutputStream --->继承了OutputStream,具体实现了向文件中写入byte数据的方法

public class FileOutputStreamDemo1 {public static void main(String[] args)throws IOException{//如果文件不存在,则创建该文件,如果该文件存在,则删除后再重新创建FileOutputStream fos = new FileOutputStream("demo.dat",true);/* * 如果文件不存在,则创建该文件,如果文件存在,则以追加的方式向文件中写数据 * FileOutputStream fos = new FileOutputStream("demo.dat","true"); */fos.write('A');  //写一个字节String s = "中国";byte[] b = s.getBytes();fos.write(b); //写一个字节数组fos.close();}public static void  copyFile(File srcFile,File destFile)throws IOException{if(!srcFile.exists())throw new IllegalArgumentException("原文件"+srcFile+"不存在");if(!srcFile.isFile())throw new IllegalArgumentException(srcFile+"不是文件");FileInputStream in = new FileInputStream(srcFile);FileOutputStream out = new FileOutputStream(destFile);byte[] buf = new byte[10*1024];int n;while((n=in.read(buf, 0, buf.length))!=-1){out.write(buf, 0, n);}}}

DataInputStrean 和 DataOutputStrean  采用装饰模式,底层包装一个字节的读取操作

                out.writeInt(10);out.writeInt(-10);out.writeLong(10l);out.writeDouble(1.11);out.writeUTF("中国");out.writeChars("中国人");
DataInputStrean中有与之对应的read操作


带缓冲的字节流

BufferedInputStreamBufferedOutputStream,为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式,提高了IO的性能

public static void  copyFileBuffer(File srcFile,File destFile)throws IOException{if(!srcFile.exists())throw new IllegalArgumentException("原文件"+srcFile+"不存在");if(!srcFile.isFile())throw new IllegalArgumentException(srcFile+"不是文件");BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));int n;while((n=in.read())!=-1){out.write(n);out.flush();//必须写}in.close();out.close();}



还可以自己写一个copyFileByByte(),经过比较,在进行较大的文件的copy工作时,自己创建byte[] 数组批量读取时,速度最快,带缓冲区的方式次之,当然可以想到,单个字节拷贝方式最慢。


字符流

1>认识文本和文本文件

java文本(char) 是16位无符号整数,是字符的Unicode编码(双字节编码)

文件是byte byte byte 。。 的序列集合

文本文件是文本按照一定的编码方式序列化为byte的存储方式

2>字符流(Reader Writer)

字符流的底层仍然是基本的字节序列

字符流的基本实现  ---->操作文本文本文件

   InputStreamReader -->完成byte流 解析为 char流 ,按照编码解析 

   OutputStreamWrite -->完成char流到byte流的解析,同样按照编码解析

public class FIRandFOW {public static void main(String[] args)throws IOException{FileInputStream in = new FileInputStream("C:\\unintall.log");/* * 可以指定编码方式,自动识别换行 */InputStreamReader reader = new InputStreamReader(in,"GBk");FileOutputStream out = new FileOutputStream("C:\\unintall1.log");OutputStreamWriter writer = new OutputStreamWriter(out,"GBk");int a;/* 单个字符读取while((a = reader.read())!=-1){System.out.print((char)a);}*///批量读取char[] buffer = new char[8*1024];while((a=reader.read(buffer,0,buffer.length))!=-1){writer.write(buffer, 0, a);writer.flush();//要加上刷新,才能及时将字符数组中的内容输出到文件String s = new String(buffer,0,a);System.out.println(s);}}}

FileReader 和 FileWriter


同 InputStreamReader  和 OutputStreamWriter读取字符和字符数组方式一样,只是创建对象的方式不同

DataInputStrean
FileReader read = new FileReader(file);
FileWriter write = new FileWriter(file);  构造函数的参数是File对象

注:这种字符流操作存在一些缺陷,我们看到在构造方法中没办法指定编码方式,所以,读取文件的编码必须和文件的编码相同,不然会出现乱码


字符流的过滤器

BufferedReader 和 BufferedWriter PrintWriter
优点是能以行为单位进行文件的读取

public class BufferReaderWriter{public static void main(String[] args) throws IOException{BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\unintall.log"),"GBK"));    //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\unintall1.log")));    PrintWriter pwriter = new PrintWriter("C:\\unintall1.log");    String line;    /*    while((line = reader.readLine()) != null)    {    writer.write(line);//不识别换行    writer.newLine();//手动换行    writer.flush();    System.out.println(line);    }*/    /*     * 由于BufferedWriter创建对象比较复杂,并且不识别换行,所以用PrintWriter替代     */    while((line = reader.readLine()) != null)    {    pwriter.println(line); //用该方法进行换行    pwriter.flush();    System.out.println(line);    }}}

以上就是javaIO的基本类以及常用的操作,我们完全可以参照这篇文章对API中的其他IO类进行扩展学习



DataInputStrean
1 0