java的文件操作基本可以分为两个类型:
- 基于字节操作,如:InputStream 和 OutputStream
- 基于字符操作,如:Writer 和 Reader
一、基于字节
先来看看InputStream的类层次结构:
用的比较多的是FileInutStream。
再来看看OutputStream的结构:
二、基于字符
还是先看看类层次结构图,先看Reader:
然后是Writer:
三、代码示例
先额外贴一段关于控制台输入的:
1 //从控制台接收用户输入 Scanner 2 public String getInputByScanner() { 3 Scanner sc = new Scanner(System.in);//这里也可以指定编码 4 System.out.println("waiting input:"); 5 String line = sc.next(); 6 return line; 7 } 8 9 //从控制台接收用户输入 BufferedReader 10 public String getInputByBufferedReader() { 11 System.out.println("waiting input:"); 12 String line = ""; 13 try { 14 BufferedReader bt = new BufferedReader(new InputStreamReader(System.in)); 15 line = bt.readLine(); 16 } catch (IOException ex) { 17 ex.printStackTrace(); 18 } 19 return line; 20 }
再来看看基于字节的文件读取,这里可以一次读取一个字节,也可以一次读取多个字节。
1 /** 2 * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。 3 * 一次读取一个字节 4 */ 5 public void readFileByByte(String fileName) { 6 File file = new File(fileName); 7 InputStream in = null; 8 try { 9 System.out.println("以字节为单位读取文件内容,一次读一个字节:"); 10 // 一次读一个字节 11 in = new FileInputStream(file); 12 int tempbyte; 13 while ((tempbyte = in.read()) != -1) { 14 System.out.write(tempbyte); 15 } 16 in.close(); 17 } catch (IOException e) { 18 e.printStackTrace(); 19 return; 20 }finally { 21 if (in != null) { 22 try { 23 in.close(); 24 } catch (IOException e1) { 25 } 26 } 27 } 28 } 29 30 /** 31 * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。 32 * 一次读取多个字节 33 */ 34 public void readFileByBytes(String fileName) { 35 File file = new File(fileName); 36 InputStream in = null; 37 try { 38 System.out.println("以字节为单位读取文件内容,一次读多个字节:"); 39 // 一次读多个字节 40 byte[] tempbytes = new byte[200]; 41 int bytesRead = 0; 42 in = new FileInputStream(file); 43 System.out.println("当前字节输入流中的字节数为:" + in.available()); 44 // 读入多个字节到字节数组中,byteread为一次读入的字节数 45 while ((bytesRead = in.read(tempbytes)) != -1) { 46 System.out.write(tempbytes, 0, bytesRead); 47 } 48 } catch (Exception e1) { 49 e1.printStackTrace(); 50 } finally { 51 if (in != null) { 52 try { 53 in.close(); 54 } catch (IOException e1) { 55 } 56 } 57 } 58 }
FileInputStream的read(byte[] b)方法,一次将最多b.length
个字节的数据读入一个 byte数组中,它返回读取的字节数。
基于字符的文件读取:
1 /** 2 * 以字符为单位读取文件,常用于读文本,数字等类型的文件 3 * 一次读一个字符 4 */ 5 public void readFileByChar(String fileName) { 6 File file = new File(fileName); 7 Reader reader = null; 8 try { 9 System.out.println("以字符为单位读取文件内容,一次读一个字符:"); 10 // 一次读一个字符 11 reader = new InputStreamReader(new FileInputStream(file)); 12 int tempchar; 13 while ((tempchar = reader.read()) != -1) { 14 // 对于windows下,\r\n这两个字符在一起时,表示一个换行。 15 // 但如果这两个字符分开显示时,会换两次行。 16 // 因此,屏蔽掉\r,或者屏蔽\n。否则,将会多出很多空行。 17 if (((char) tempchar) != '\r') { 18 System.out.print((char) tempchar); 19 } 20 } 21 reader.close(); 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 } 26 27 /** 28 * 以字符为单位读取文件,常用于读文本,数字等类型的文件 29 * 一次读一个字符 30 */ 31 public void readFileByChars(String fileName) { 32 File file = new File(fileName); 33 Reader reader = null; 34 try { 35 System.out.println("以字符为单位读取文件内容,一次读多个字节:"); 36 // 一次读多个字符 37 char[] tempchars = new char[30]; 38 int charReadCount = 0; 39 reader = new InputStreamReader(new FileInputStream(file)); 40 // 读入多个字符到字符数组中,charread为一次读取字符数 41 while ((charReadCount = reader.read(tempchars)) != -1) { 42 // 同样屏蔽掉\r不显示 43 if ((charReadCount == tempchars.length) 44 && (tempchars[tempchars.length - 1] != '\r')) { 45 System.out.print(tempchars); 46 } else { 47 for (int i = 0; i < charReadCount; i++) { 48 if (tempchars[i] == '\r') { 49 continue; 50 } else { 51 System.out.print(tempchars[i]); 52 } 53 } 54 } 55 } 56 57 } catch (Exception e1) { 58 e1.printStackTrace(); 59 } finally { 60 if (reader != null) { 61 try { 62 reader.close(); 63 } catch (IOException e1) { 64 } 65 } 66 } 67 }
没啥好解释的,接下来看2个基于字符的读取的变化版(按行读取):
①按照行读取:
1 /** 2 * 以行为单位读取文件,常用于读面向行的格式化文件 3 * 一次读一整行 4 */ 5 public void readFileByLines(String fileName) { 6 File file = new File(fileName); 7 BufferedReader reader = null; 8 try { 9 System.out.println("以行为单位读取文件内容,一次读一整行:"); 10 reader = new BufferedReader(new FileReader(file)); 11 String tempString = null; 12 int line = 1; 13 // 一次读入一行,直到读入null为文件结束 14 while ((tempString = reader.readLine()) != null) { 15 // 显示行号 16 System.out.println("line " + line + ": " + tempString); 17 line++; 18 } 19 reader.close(); 20 } catch (IOException e) { 21 e.printStackTrace(); 22 } finally { 23 if (reader != null) { 24 try { 25 reader.close(); 26 } catch (IOException e1) { 27 } 28 } 29 } 30 }
②随机读取:
1 /** 2 * 随机读取文件内容 3 */ 4 public void readFileByRandomAccess(String fileName) { 5 RandomAccessFile randomFile = null; 6 try { 7 System.out.println("随机读取一段文件内容:"); 8 // 打开一个随机访问文件流,按只读方式 9 randomFile = new RandomAccessFile(fileName, "r"); 10 // 文件长度,字节数 11 long fileLength = randomFile.length(); 12 // 读文件的起始位置 13 int beginIndex = (fileLength > 10) ? 10 : 0; 14 // 将读文件的开始位置移到beginIndex位置。 15 randomFile.seek(beginIndex); 16 byte[] bytes = new byte[10]; 17 int byteread = 0; 18 // 一次读10个字节,如果文件内容不足10个字节,则读剩下的字节。 19 // 将一次读取的字节数赋给byteread 20 while ((byteread = randomFile.read(bytes)) != -1) { 21 System.out.write(bytes, 0, byteread); 22 } 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } finally { 26 if (randomFile != null) { 27 try { 28 randomFile.close(); 29 } catch (IOException e1) { 30 } 31 } 32 } 33 }
文件读取基本就这些,下面看2个写文件的操作,大多数情况下,我们需要做的是向现有的文件末尾加入一些文字,所以这里主要介绍向文件末尾追加文字的方法:
1 /** 2 * 使用RandomAccessFile 3 */ 4 public void appendMethod1(String fileName, String content) { 5 try { 6 // 打开一个随机访问文件流,按读写方式 7 RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw"); 8 // 文件长度,字节数 9 long fileLength = randomFile.length(); 10 //将写文件指针移到文件尾。 11 randomFile.seek(fileLength); 12 randomFile.writeBytes(content); 13 randomFile.close(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 19 /** 20 * 使用FileWriter 21 */ 22 public void appendMethod2(String fileName, String content) { 23 try { 24 //打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件 25 FileWriter writer = new FileWriter(fileName, true); 26 writer.write(content); 27 writer.close(); 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } 31 }
最后,说一下编码问题。有些时候,我们需要指定读取文件的编码,这时候一般就要用到InputStreamReader或OutputStreamWriter。
Java的API这样描述的:
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。 每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。 为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如: BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
例如:BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filename),"GB2312"));
更多资料可参照:
http://www.cnblogs.com/zhuocheng/archive/2011/12/12/2285290.html