Java IO流
流的概念:
流是一种有顺序的,有起点和终点的字节集合,是对数据传输的总成或抽象。即数据在两设备之间的传输称之为流,
流的本质是数据传输,根据数据传输的特性讲流抽象为各种类,方便更直观的进行数据操作。
IO流的分类:
根据数据处理类的不同分为: 字符流和字节流。
根据数据流向不同分为: 输入流和输出流。
字节流和字符流:
字符流的由来:因为数据编码的不同,而有了对字符进行高效操作的流对象,其本质就是基于字节流读取时,去查了指定的码表。字符流和字节流的区别:
(1)读写单位不同:字节流一字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(例如图片,avi),而字符流只能处理字符类型的数据。
(3)字节流操作的时候本身是不会用到缓冲区的,是对文件本身的直接操作。而字符流在操作的时候是会用到缓冲区的,通过缓冲区来操作文件。
结论:优先使用字节流,首先因为在硬盘上所有的文件都是以字节的形式进行传输或保存的,包括图片等内容。但是字符流只是在内存中才会形成,所以在开发中字节流使用广泛。
public class IO_Demo { //创建一个新的文件 public static void main(String[] args) { File f = new File("G://hello.txt"); try { f.createNewFile(); } catch (Exception e) { e.printStackTrace(); } } //File类的两个常量 public static void main(String[] args) { System.out.println(File.separator); // "\" System.out.println(File.pathSeparator); // ";" } /* 此处多说几句:有些同学可能认为,我直接在windows下使用\进行分割不行吗? 当然是可以的。但是在linux下就不是\了。 所以,要想使得我们的代码跨平台,更加健壮, 所以,大家都采用这两个常量吧,其实也多写不了几行。 */ public static void main(String[] args) { String fileName = "G:"+File.separator+"hello.txt"; File f = new File(fileName); try { f.createNewFile(); System.out.println(fileName); } catch (Exception e) { e.printStackTrace(); } } //删除一个文件 public static void main(String[] args) { String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); try { f.delete(); } catch (Exception e) { e.printStackTrace(); } } //创建一个文件夹 public static void main(String[] args) { String fileName = "G:" + File.separator + "hello"; File f = new File(fileName); f.mkdirs(); } //列出指定目录下的全部文件(文件/文件夹,包括隐藏文件) //list()返回的是String数组,并不是完整的路径,如果要返回完整的路径,使用listFiles(),它返回的是File的数组 public static void main(String[] args) { String fileName = "D:" + File.separator; File f = new File(fileName); String[] str = f.list(); //返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。 File[] fileStr = f.listFiles(); for (int i = 0; i < str.length; i++) { System.out.println(str[i]); } for (int i = 0; i < fileStr.length; i++) { System.out.println(fileStr[i]); } } //判断一个指定路径是否为目录 public static void main(String[] args) { String fileName = "D:" + File.separator; File f = new File(fileName); if (f.isDirectory()) { System.out.println("YES"); } else { System.out.println("NO"); } } /** * 字节流 */ //向文中写入字符串 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator+"hello.txt"; File f = new File(fileName); OutputStream out = new FileOutputStream(f); String str = "你好"; byte[] b = str.getBytes(); out.write(b); out.close(); } //向文中追加新内容 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); OutputStream out = new FileOutputStream(f,true); String str = "Hello"; // String str = "\r\nHello"; //换行 byte[] b = str.getBytes(); for (int i = 0; i < b.length; i++) { out.write(b[i]); } out.close(); } //读取文件内容 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); InputStream in = new FileInputStream(f); byte[] b = new byte[1024]; in.read(b); in.close(); System.out.println(new String(b).trim()); } /* 观察上面的例子可以看出,我们预先申请了一个指定大小的空间, 但有时这个空间可能会太小,或者是太大,我们需要准确的大小,这样子可以节省空间 */ //字节流 读取文件内内容,节省空间 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); InputStream in = new FileInputStream(f); byte[] b = new byte[(int)f.length()]; in.read(b); System.out.println("文件长度为: " + f.length()); in.close(); System.out.println(new String(b).trim()); } /* 上面的几个例子都是在知道文件的内容多大,然后才展开的,有时候我们不知道文件有多大, 这种情况下,我们需要判断是否独到文件的末尾。 当独到文件末尾的时候会返回-1.正常情况下是不会返回-1的 */ public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); InputStream in = new FileInputStream(f); byte[] b = new byte[1024]; int count = 0; int temp = 0; while ((temp = in.read()) != (-1)) { b[count++] = (byte)temp; } in.close(); System.out.println(new String(b).trim()); } /** * 字符流 */ //向文中写入数据 /* 其实这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。 当你如果想问文件中追加内容的时候,可以使用将上面的声明out的那一行换为: Writer out =new FileWriter(f,true); 这样,当你运行程序的时候,会发现文件内容变为: hellohello 如果想在文件中换行的话,需要使用“\r\n” 比如将str变为String str="\r\nhello"; 这样文件追加的str的内容就会换行了。 */ public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); Writer out = new FileWriter(f,true); String str = "Hi!"; // String str = "\r\nHello"; //换行 out.write(str); out.close(); } //从文中读取内容 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); char[] ch = new char[100]; Reader reader = new FileReader(f); int count = reader.read(ch); reader.close(); System.out.println("读入长度为: " + count); System.out.println("内容为: "+new String(ch,0,count)); } //当然最好采用循环读取的方式,因为我们有时候不知道文件到底有多大。 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); char[] ch = new char[100]; Reader reader = new FileReader(f); int temp = 0; int count = 0; while ((temp = reader.read()) != (-1)) { ch[count++] = (char)temp; } reader.close(); System.out.println("内容为: "+new String(ch,0,count)); } /** * 关于字节流和字符流的区别? * 实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,但是字符流在操作的时候是会用到缓冲区的,是通过缓冲区来操作文件的。 * * 使用字节流好还是字符流好呢? * 答案是字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。 */ /** * OutputStreramWriter 和InputStreamReader类 * 整个IO类中除了字节流和字符流还包括字节和字符转换流。 * OutputStreramWriter将输出的字符流转化为字节流 * InputStreamReader将输入的字节流转换为字符流 * 但是不管如何操作,最后都是以字节的形式保存在文件中的。 */ //字节输出流转化为字符输出流 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); Writer out = new OutputStreamWriter(new FileOutputStream(f)); out.write("hahaha"); out.close(); } //将字节输入流转换为字符输入流 public static void main(String[] args) throws Exception{ String fileName = "G:" + File.separator + "hello.txt"; File f = new File(fileName); Reader reader = new InputStreamReader(new FileInputStream(f)); char[] c = new char[100]; int len = reader.read(c); System.out.println(new String(c, 0, len)); reader.close(); } }
参考来源: http://www.cnblogs.com/rollenholt/archive/2011/09/11/2173787.html
下面的是我自己工作中用到的IO代码...
IO读取超大文件
package com.reader.big.file; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; public class ReaderBigFile { public static void main(String[] args) throws Exception { oldIOReadFile(); } public static void oldIOReadFile() throws IOException{ BufferedReader br = new BufferedReader(new FileReader("J:\\cachefile\\01010999201601140900")); PrintWriter pw = new PrintWriter("J:\\hfcollection\\20160114"); char[] c = new char[100*1024*1024]; for(;;){ if(br.read(c)!=-1){ pw.print(c); }else{ break; } } pw.close(); br.close(); } }
压缩文件
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class ZipCompress { /** * 多文件 打包压缩文件 * * @param files 目标文件路径 * @param zipfile 压缩文件路径 * @return * @throws Exception */ public static boolean zipFiles(String files, String zipfile) throws Exception { boolean bf = true; // 根据文件路径构造一个文件实例 File ff = new File(zipfile); // 判断目前文件是否存在,如果不存在,则新建一个 if (!ff.exists()) { ff.createNewFile(); } // 根据文件路径构造一个文件输出流 FileOutputStream out = new FileOutputStream(zipfile); // 传入文件输出流对象,创建ZIP数据输出流对象 ZipOutputStream zipOut = new ZipOutputStream(out); File f = new File(files); if (!f.exists()) { bf = false; } try { // 创建文件输入流对象 FileInputStream in = new FileInputStream(files); // 得到当前文件的文件名称 String fileName = files.substring(files.lastIndexOf('\\') + 1, files.length()); // 创建指向压缩原始文件的入口 ZipEntry entry = new ZipEntry(fileName); zipOut.putNextEntry(entry); // 向压缩文件中输出数据 int nNumber = 0; byte[] buffer = new byte[512]; while ((nNumber = in.read(buffer)) != -1) { zipOut.write(buffer, 0, nNumber); } // 关闭创建的流对象 in.close(); } catch (IOException e) { e.printStackTrace(); bf = false; } zipOut.close(); out.close(); return bf; } }