1. IO流的作用是读写设备上的数据,如硬盘文件、内存、键盘、网络等。根据数据走向,可分为:输入流和输出流;根据处理的数据类型,可分为:字节流和字符流。字节流可以处理所有类型的数据,如MP3、图片、视频等。在读取时,读到一个字节就返回一个字节。在Java中都是以“Stream”结尾的;字符流仅能够处理纯文本数据,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。在Java中对应的类都是以“Reader”或“Writer”结尾。
2. 字符、字节与编码
说明 | 举例 | |
字符 | 人们使用的记号,抽象意义上的一个符号 | '1','中','a',’$‘ |
字节 | 计算机中存储数据的单元,一个8位的二进制数,是一个很具体的存储空间 | 0x01,0x45,0xFA |
ANSI编码 | 系统预设的标准文字存储格式,不是具体的某一种编码,不同的国家和地区使用不同的标准。ANSI编码的一个字符可能使用一个字节或多个字节来表示 |
"中文123" (占7字节) |
UNICODE编码 | 为了是国际间信息交流更加方便,国际组织制定了UNICODE字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换,、处理的要求 |
L“中文123” (占10字节) |
3. 使用字节流读取文本数据
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class ReadByteStream { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("text.txt"); byte[] input = new byte[30]; fis.read(input); String inputString = new String(input,"GBK"); System.out.println(inputString); // 关闭输入流
fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
4. 使用字节流写入数据
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class ReadByteStream { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("text.txt"); byte[] input = new byte[30]; fis.read(input); String inputString = new String(input,"GBK"); System.out.println(inputString); // 关闭输入流 fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
5. 文件的的拷贝
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class CopyByByteStream { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("破碎的瞬间.jpg"); FileOutputStream fos = new FileOutputStream("new.jpg"); byte[] input = new byte[50]; while(fis.read(input) != -1){ fos.write(input); } fos.close(); fis.close(); System.out.println("done"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
6. 使用缓冲流读写大文件,其读写的速度比普通的字节流快的多
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class ReadByBufferedByteStream { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("破碎的瞬间.jpg"); BufferedInputStream bis = new BufferedInputStream(fis); // 合理的设置缓冲区的大小,可以对读写效率进行优化 FileOutputStream fos = new FileOutputStream("new1.jpg"); BufferedOutputStream bos = new BufferedOutputStream(fos); // 合理的设置缓冲区的大小,可以对读写效率进行优化
// 字节数组的大小设置原则:大型文件对应的数组可以大一些,小文件对应的数组大小可以小一些 byte[] input = new byte[100]; int count = 0; long startTime = System.currentTimeMillis(); while(bis.read(input) != -1){ bos.write(input); count++; //计算读取次数 } bos.close(); fos.close(); bis.close(); fis.close(); long endTime = System.currentTimeMillis(); System.out.println(endTime-startTime); System.out.println("读取了"+count+"次"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
7. 使用字符流读写文件
import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; public class ReadWriteByCharStream { public static void main(String[] args) { try { File file = new File("test.txt"); FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream("test1.txt"); // 编码设置一致 InputStreamReader isr = new InputStreamReader(fis, "GBK"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); char input[] = new char[100]; // 加入length防止读取多余数据 int length = 0; while((length = isr.read(input)) != -1){ String inputString = new String(input,0,length); osw.write(inputString); } osw.close(); isr.close(); fos.close(); fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
8. 使用带有缓冲的字符流可以读取或写入文件的一行数据,且可以提高读写的效率
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; public class ReadWriteBufferedCharStream { public static void main(String[] args) { try { File file = new File("test.txt"); FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream("test2_buffered.txt"); // 编码设置一致 InputStreamReader isr = new InputStreamReader(fis, "GBK"); OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); // 创建带有buffer的字符流 BufferedReader br = new BufferedReader(isr); // BufferedWriter bw = new BufferedWriter(osw); PrintWriter pw = new PrintWriter(osw,true);// 自动flush String input = null; while((input = br.readLine()) != null){ //bw.write(input); // 不包含换行符 pw.println(input); } br.close(); // 将缓冲区的内容强制输出,避免遗漏 //bw.flush()bw.close(); pw.close(); osw.close(); isr.close(); fos.close(); fis.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
9. FileReader和FileWriter,处理文本文件
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class TestFileReadWrite { public static void main(String[] args) { try { // 读取文本文件 FileReader fr = new FileReader("test.txt"); BufferedReader br = new BufferedReader(fr); FileWriter fw = new FileWriter("test_new.txt"); BufferedWriter bw = new BufferedWriter(fw); String line; while((line = br.readLine()) != null){ bw.write(line+" "); } // 所有带有缓冲的流都需要强制输出 bw.flush(); bw.close(); fw.close(); br.close(); fr.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
10. RandomAccessFile随机文件读写
使用多线程在一个文件指定的块位置写入数据。
import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; public class MultiWriteFile { public static void main(String[] args) { File file = new File("test.txt"); if(file.exists()){ file.delete(); } // 调用多个线程分区写入文件,且如果写入的数据的长度小于块的长度,则块间的空白处仍保留,最后一个块除外 new WriteFile(file, 2).start(); new WriteFile(file, 1).start(); new WriteFile(file, 5).start(); new WriteFile(file, 4).start(); new WriteFile(file, 3).start(); // 读取文件 try { RandomAccessFile raf = new RandomAccessFile(file, "r"); raf.seek(400); //读取400位置的数据 byte[] output = new byte[20]; raf.read(output); String str = new String(output); System.out.println(str); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; public class WriteFile extends Thread{ File file; int block; // 块号 int lenByte = 100; //块的字节大小 public WriteFile(File f,int b){ file = f; block = b; } public void run(){ try { RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.seek((block-1)*lenByte); //定位到文件的位置 raf.writeBytes("I am ws"+block); //在相应的位置写入数据 for(int i = 0; i < 20; i++){ raf.writeBytes("-"); } raf.writeBytes(" "); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
11. Apache IO库commons.io的功能十分强大,可参考common.io的使用。