JAVA IO

来源:互联网 发布:千岛湖惨案 知乎 编辑:程序博客网 时间:2024/04/27 20:38
一、关于Java IO的概述

  • IO流用来处理设备之间的数据传输
  • Java对数据的操作是通过流的方式
  • Java用于操作流的对象都在IO包中
  • IO流按照流向划分为输入流、输出流
  • IO流按照操作数据划分为字符流(专门处理文字)、字节流
我理解的程序处理数据过程大致如下:

二、File相关操作

一个File类的实例代表一个文件或文件夹,File.pathSeparator指的是分隔连续多个路径字符串的分隔符,File.separator才是用来分隔同一个路径字符串中的目录的。由于java可跨平台,所以当new一个File时,路径中的“;"和"/"要用File.pathSeparator和File.separator代替。

File常用的构造方法

import java.io.File;public class IOTest {public static void main(String[] args) {File file1=new File("D:"+File.separator+"IOTest.Java");//文件绝对路径File file2=new File("D:"+File.separator+"IO");//目录的绝对路径File file3=new File(file2, "IOTest.java");//第一个参数File实例代表一个目录file2,第二个参数为file2目录内的文件名File file4=new File("D:"+File.separator+"IO", "IOTest.java");//目录和文件的字符串类型}}
File的常用方法

file1.createNewFile();System.out.println("file1.isFile():  " + file1.isFile());System.out.println("file1.isDirectory():  " + file1.isDirectory());System.out.println("file1.getName():  " + file1.getName());System.out.println("file1.getAbsolutePath  " + file1.getAbsolutePath());file2.mkdir();System.out.println("file2.isDirectory():  " + file1.isDirectory());String[] list = file2.list();//返回String[]类型的文件 只含文件名File[] listFile=file2.listFiles();//返回File[]类型的文件 包含完整的文件对象


其他相关方法的总结如下:

  • String getName():返回文件名或路径名(若是路径,返回最后一级子路径名)
  • String getPath():返回对象对应的路径名
  • File  getAbsoluteFile():返回绝对路径
  • String getAbsolutePath():返回对象对应的绝对路径
  • String getParent():返回文件目录的上一级目录名
  • boolean renameTo(File newName):重命名此File对象对应的文件或目录,若重命名成功返回true;
  • boolean exists():判断对象对应的文件或目录是否存在;
  • boolean canWrite():判断对象对应文件或目录是否可写;
  • boolean canRead():判断对象对应文件或目录是否可读;
  • boolean isFile():判断对象是文件,不是目录;
  • boolean isDirectory()  判断对象的文件是否是一个目录; 
  • boolean isAbsolute() 判断对象对应文件或目录是否为绝对路径名; 
  • boolean createNewFile() 当且仅当不存在,该方法创建一个该File对象所指定的新文件,创建成功返回true。 
  • boolean delete():删除File对象所对应的文件或路径;
  • boolean mkdir() 创建File对象所对应的目录,调用该方法的File对象必须对应路径,而不是文件。
  • String[] list():列出File对象的所有子文件名和路径名。
  • File[] listFiles():列出File对象的所有子文件和路径。
  • static File[] listRoots():列出系统所有的根路径;
对文件的操作前要判断文件是否存在,再做进一步io操作。


练习列出一个目录下所有文件及目录(利用递归):

public class IOTest {public static void main(String[] args) throws Exception {File file = new File("C:\\Users\\Mr\\Desktop\\源码");scan(file);}private static void scan(File file) {// TODO Auto-generated method stubFile[] files = file.listFiles();for (int i = 0; i < files.length; i++) {File newfile = files[i];if (newfile.isFile()) {System.out.println("文件:" + newfile.getName());} else {System.out.println("目录:" + newfile.getName());scan(newfile);}}}}

文件过滤器,根据文件名或路径获得想要的文件对象

private static void scan(File file) {// TODO Auto-generated method stubFile[] files = file.listFiles(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {// TODO Auto-generated method stubreturn name.contains(".java");}});System.out.println(Arrays.toString(files));}
通过listfile方法传入一个FilenameFilter接口的实例,复写accept方法,控制想要得到的文件。

三、流

  • 字符流

FileReader(直接读取)

import java.io.File;import java.io.FileReader;public class FileReaderTest   {public static void main(String[] args) throws Exception{File file=new File("d:"+File.separator+"test4.txt");FileReader reader=new FileReader(file);int ch=0;while((ch=reader.read())!=-1){System.out.print((char)ch);}reader.close();}}

利用字符数组读取以提高效率

import java.io.File;import java.io.FileReader;public class FileReaderTest {public static void main(String[] args) throws Exception {File file = new File("d:" + File.separator + "test4.txt");FileReader reader = new FileReader(file);char[] buf = new char[1024];int len = 0;while ((len = reader.read(buf)) != -1) {System.out.print(new String(buf, 0, len));}reader.close();}}

FileWriter(现有文件追加一行)

import java.io.File;import java.io.FileWriter;public class FileWriterTest {public static void main(String[] args) throws Exception{File file = new File("d:" + File.separator + "test4.txt");if(!file.exists())file.createNewFile();FileWriter writer=new FileWriter(file,true);//可追加设为truewriter.write("\r\n-------新追加一行--------");writer.close();}}

文本文件复制

import java.io.File;import java.io.FileReader;import java.io.FileWriter;public class Copy {public static void main(String[] args) throws Exception {File source = new File("d:" + File.separator + "test4.txt");File target = new File("d:" + File.separator + "test5.txt");if (!target.exists())target.createNewFile();FileReader reader = new FileReader(source);FileWriter writer = new FileWriter(target, true);char[] buf = new char[1024];int len = 0;while ((len = reader.read(buf)) != -1) {writer.write(buf, 0, len);writer.flush();}writer.close();reader.close();}}

  • 字符缓冲流
BufferedReader

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;public class BufferedReaderTest {public static void main(String[] args) throws Exception {BufferedReader reader=new BufferedReader(new FileReader("d:" + File.separator + "test4.txt"));String line;while((line=reader.readLine())!=null){System.out.println(line);}}}

BufferedWriter

import java.io.BufferedWriter;import java.io.File;import java.io.FileWriter;public class BufferedWriterTest {public static void main(String[] args) throws Exception {BufferedWriter writer=new BufferedWriter(new FileWriter("d:" + File.separator + "test5.txt",true));writer.newLine();writer.write("新追加一行");writer.flush();writer.close();}}


文本文件复制(字符缓冲流)

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileReader;import java.io.FileWriter;public class CopyByBuf {public static void main(String[] args) throws Exception {File source = new File("d:" + File.separator + "test4.txt");File target = new File("d:" + File.separator + "test6.txt");if (!target.exists())target.createNewFile();BufferedReader reader = new BufferedReader(new FileReader(source));BufferedWriter writer = new BufferedWriter(new FileWriter(target));String line;while ((line = reader.readLine()) != null) {writer.write(line);writer.newLine();writer.flush();}writer.close();reader.close();}}

BufferedReader的子类LineNumberReader.setLineNumber(0)来设置初始行,默认0,getLineNumber()返回行号。

public class BufferedReaderTest {public static void main(String[] args) throws Exception {LineNumberReader reader=new LineNumberReader(new FileReader("d:" + File.separator + "test4.txt"));String line;//reader.setLineNumber(0);while((line=reader.readLine())!=null){System.out.println(reader.getLineNumber()+line);}}}

  • 字节流
FileInputStream直接读取

public class FileInputStreamTest { public static void main(String[] args) throws Exception { FileInputStream in = new FileInputStream("d:" + File.separator + "test4.txt");int ch = 0;while ((ch = in.read()) != -1) {System.out.print((char) ch);}in.close();}}
FileInputStream通过byte[]读取
public class FileInputStreamTest {public static void main(String[] args) throws Exception {FileInputStream in = new FileInputStream("d:" + File.separator + "test4.txt");byte[] buf = new byte[1024];int len = 0;while ((len = in.read(buf)) != -1) {System.out.print(new String(buf, 0, len));} in.close();}}
FileOutputStream直接写入数据
public class FileInputStreamTest {public static void main(String[] args) throws Exception {FileOutputStream out=new FileOutputStream("d:" + File.separator + "test.txt");out.write("黑马你好".getBytes("UTF-8"));out.close(); }}
FileOutputStream和FileInputStream通过byte[]图片
public class FileInputStreamTest {public static void main(String[] args) throws Exception {FileInputStream in = new FileInputStream("d:" + File.separator + "heima.jpg");FileOutputStream out=new FileOutputStream("d:" + File.separator + "heima_copy.jpg");byte[] buf = new byte[1024];int len = 0;while ((len = in.read(buf)) != -1) {out.write(buf, 0, len);}in.close();out.close();}}
FileOutputStream和FileInputStream通过BufferedOutputStream和BufferedInputStream复制图片
public class FileInputStreamTest {public static void main(String[] args) throws Exception {BufferedInputStream in=new BufferedInputStream(new FileInputStream("d:" + File.separator + "heima.jpg"));BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream("d:" + File.separator + "heima_copy1.jpg"));int data = 0;while ((data = in.read()) != -1) {out.write(data);}in.close();out.close();}}

  • 转换流
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。
而它们都是属于字节流,现在要实现对控制台输入的字符串打印或其他操作,由于是对文本进行操作,FileReader和FileWriter更为方便,怎样将要操作的字节流转换为字符流然后进行操作呢?这里可以用转换流InputStreamReader和OutputStreamReader:
package Blog;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.InputStreamReader;import java.io.OutputStreamWriter;public class ConsoleTest {public static void main(String[] args) throws Exception {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;while (!"stop".equals(line) && (line = reader.readLine()) != null) {writer.write(line);writer.newLine();writer.flush();}writer.close();reader.close();}}
  • 字符流与字节流的总结
字节流和字符流在处理数据时代码和流程大致相同,字符流其根本也是用的字节流,但是为了处理文字方便加入了类似缓冲块的概念,使其字符流可以对文字的编码进行操作,避免乱码的出现,正因为有了缓冲,所以每次写入后需要flush操作将其刷进目标中,而字节流则不需要。并且字符流读取后close方法时也会对缓冲区进行刷新操作。字符流和字节流两者相比,字节流通用可以处理任何类型数据,但处理处理文本时,由于字符流的编码特性是最为合适的,并且字符流提供了专门处理文本的方便方法,而处理非文本时,一定要使用字节流,如果使用字符流可能复制成功后文件仍无法读取。
  • 用流对目录复制
将C盘下目录复制到D盘
package Blog;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;public class CopyDir {public static void main(String[] args) throws Exception {File dir_s = new File("c:" + File.separator + "heima");//源目录File dir_d = new File("d:" + File.separator + dir_s.getName());//目标目录dir_d.mkdir();//创建目录DoCopy(dir_s, dir_d);}private static void DoCopy(File dir_s, File dir_d) throws Exception {// TODO Auto-generated method stubFile[] files = dir_s.listFiles();for (File file : files) {if (file.isFile()) {//如果是文件 复制BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));File file_new=new File(dir_d, file.getName());file_new.createNewFile();BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file_new));int data = 0;while ((data = in.read()) != -1) {out.write(data);}in.close();out.close();} else {//如果是目录 递归File dir_new=new File(dir_d,file.getName());dir_new.mkdir();DoCopy(file,dir_new);//}}}}
输入两个目录,作为源和目的,将源目录中所有.java文件复制到目的目录中同时将扩展名修改为txt
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;public class Copy {public static void main(String[] args) throws Exception {System.out.println("请输入一个源目录");String SourceDir = getDir();System.out.println("请输入一个目的目录");String dtDir = getDir();mainJob(SourceDir, dtDir);System.out.println("-------------已完成-------------");}static String getDir() throws Exception {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));String str = reader.readLine();//reader.close();return str;}static void mainJob(String S, String D) throws Exception {File source = new File(S);File dest = new File(D);dest.mkdir();List<File> javaList = new ArrayList<File>();javaList = scanDir(source, javaList);for (File file : javaList) {File newFile = new File(dest,FileUtil.getHeadName(file)+".txt");int n = 0;String head=FileUtil.getHeadName(newFile);String tail=FileUtil.getExtendName(newFile);while (newFile.exists()) {//判断 若有同名文件出现时 防止覆盖newFile=new File(dest,head+"("+(++n)+")."+tail);}newFile.createNewFile();copy2dest(file, newFile);}}/** * @param source * @param javaList * @return * @throws Exception * 扫描目录筛选java文件   返回File集合 */static List<File> scanDir(File source, List<File> javaList)throws Exception {File[] javas = source.listFiles();for (File file : javas) {if (file.isDirectory()) {scanDir(file, javaList);} else {if (file.getName().endsWith(".java"))javaList.add(file);}}return javaList;}/** * @param file * @param dest * @throws Exception * 主要复制动作 */static void copy2dest(File file, File dest) throws Exception {BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));int data = 0;System.out.println("正在复制  "+dest.getName());while ((data = in.read()) != -1) {out.write(data);}in.close();out.close(); } }/** * @author Mr *自定义文件工具类 */class FileUtil{/** * @param file * @return * 获取文件名不带扩展名 */public static String getHeadName(File file){return file.getName().substring(0,file.getName().lastIndexOf("."));}/** * @param file * @return * 获取扩展名 */public static String getExtendName(File file){return file.getName().substring(file.getName().lastIndexOf(".")+1);}/** * @param file * @param extendName * @return * 修改扩展名 */public static File trExtendName(File file,String extendName){return new File(file.getParent(),getHeadName(file)+"."+extendName);}}

四、其它重要IO相关

1.可接收字符输出流和字节输出流的打印流PrintWriter,PrintWriter功能十分强大也比较常用,同时可直接接受File类型文件或String文件路径,具有自动flush的特点。

import java.io.BufferedReader;import java.io.File;import java.io.FileReader;import java.io.PrintWriter;public class PrintWriterTest  {public static void main(String[] args) throws Exception{BufferedReader reader=new BufferedReader(new FileReader("d:" + File.separator + "test4.txt"));PrintWriter printer=new PrintWriter(System.out,true);//true 自动刷新, system.out是输出流 也可以是文件File或文件路径String data=null;while((data=reader.readLine())!=null){printer.println(data);}printer.close();reader.close();}}

2.通过InputStream下的SequenceInputStream类实现合并多个字节输入流

该类有两个构造方法,也就是两种不同的实现方式:

通过传入Enumeration<? extends InputStream>对多个流的封装

public class SequenceInputStreamTest {public static void main(String[] args) throws Exception {FileInputStream in1 = new FileInputStream("d:" + File.separator+ "test4.txt");FileInputStream in2 = new FileInputStream("d:" + File.separator+ "test5.txt");FileInputStream in3 = new FileInputStream("d:" + File.separator+ "test6.txt");Vector<InputStream> vector = new Vector<InputStream>();vector.add(in1);vector.add(in2);vector.add(in3);//将三个inputStream添加进Vector集合Enumeration<InputStream> enumeration = vector.elements();//获取Enumeration对象SequenceInputStream in_all = new SequenceInputStream(enumeration);PrintWriter printer = new PrintWriter(System.out, true);BufferedReader reader = new BufferedReader(new InputStreamReader(in_all));String data = null;while ((data = reader.readLine()) != null) {printer.println(data);}reader.close();in1.close();in2.close();in2.close();in_all.close();printer.close();}}

传入两个inputStream实例对象,并且只能是两个,不常用

public class SequenceInputStreamTest {public static void main(String[] args) throws Exception {FileInputStream in1 = new FileInputStream("d:" + File.separator+ "test4.txt");FileInputStream in2 = new FileInputStream("d:" + File.separator+ "test5.txt");SequenceInputStream in_all = new SequenceInputStream(in1, in2);PrintWriter printer = new PrintWriter(System.out, true);BufferedReader reader = new BufferedReader(new InputStreamReader(in_all));String data = null;while ((data = reader.readLine()) != null) {printer.println(data);}reader.close();in1.close();in2.close();in_all.close();printer.close();}}

3.切割流

public class SplitFile {public static void main(String[] args) throws Exception{BufferedInputStream in=new BufferedInputStream(new FileInputStream("d:" + File.separator + "梁心颐 - 小树.mp3"));BufferedOutputStream out=null;byte[] data=new byte[1024*1024];int len=0;int count=0;while((len=in.read(data))!=-1){out=new BufferedOutputStream(new FileOutputStream("d:" + File.separator + "梁心颐 - 小树"+(++count)+".part"));out.write(data, 0, len);out.close();}in.close();}}

4.ObjectInputStream和ObjectOutStream实现对象持久化

要想通过该方法持久化的实例对象,该类必须实现Serializable接口

import java.io.Serializable;public class Person implements Serializable{private static final long serialVersionUID = -4102534291757583600L;private String name;private Integer age;public String add;public Person(String name, Integer age, String add) {super();this.name = name;this.age = age;this.add = add;}public Person() {// TODO Auto-generated constructor stub}}
并声明UID,如果不实现该接口则在ObjectOutputStream写出对象时会报“未序列化的对象”异常

下面开始对一个Person对象进行持久化即写入一个文件中,随后读出该文件

public class ObjectStream {public static void main(String[] args) throws Exception, IOException {Person p1=new Person("liuli", 25, "china");//写ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("D:"+File.separator+"test.obj"));out.writeObject(p1);out.close();//读ObjectInputStream in=new ObjectInputStream(new FileInputStream("D:"+File.separator+"test.obj"));Person p2=(Person)in.readObject();System.out.println(p2.getName()+p2.getAdd()+p2.getAge());}}


5.管道流

public class PipeTest {public static void main(String[] args) throws Exception {PipedInputStream pipeIn = new PipedInputStream();PipedOutputStream pipeOut = new PipedOutputStream();pipeIn.connect(pipeOut);//连接两个流In in = new In(pipeIn);Out out = new Out(pipeOut);Thread t1 = new Thread(in);Thread t2 = new Thread(out);t1.start();t2.start();}}class In implements Runnable {private PipedInputStream in;public In(PipedInputStream in) {// TODO Auto-generated constructor stubthis.in = in;}@Overridepublic void run() {// TODO Auto-generated method stubBufferedReader reader = new BufferedReader(new InputStreamReader(in));String line = null;try {while ((line = reader.readLine()) != null) {System.out.println(line);}reader.close();in.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class Out implements Runnable {private PipedOutputStream out;public Out(PipedOutputStream out) {// TODO Auto-generated constructor stubthis.out = out;}@Overridepublic void run() {// TODO Auto-generated method stubPrintWriter writer=new PrintWriter(out, true);try {writer.println("黑马程序员2015年1月9日18:51:42");writer.println("黑马程序员2015年1月9日18:51:45");writer.println("黑马程序员2015年1月9日18:51:47");writer.close();out.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
由此可见管道流建立了两个不同线程的沟通桥梁,可以实现线程间的通讯,可以实现生产者消费者模型。

6.DataInputStream和DataOutputStream存储基本数据类型数据

import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;public class DataStream {public static void main(String[] args) throws Exception{DataOutputStream out=new DataOutputStream(new FileOutputStream("d:" + File.separator + "test.txt"));out.writeInt(2015);out.writeBoolean(true);out.writeDouble(2015.0109);out.close();DataInputStream in=new DataInputStream(new FileInputStream("d:" + File.separator + "test.txt"));System.out.println(in.readInt());System.out.println(in.readBoolean());System.out.println(in.readDouble());in.close();}}

7.ByteArrayInputStream和ByteArrayOutputStream

public class ByteArrayOutputStreamTest {public static void main(String[] args) throws Exception {File file = new File("d:" + File.separator + "test4.txt");if (!file.exists())throw new RuntimeException("文件不存在");FileInputStream in;ByteArrayOutputStream arr = new ByteArrayOutputStream();in = new FileInputStream(file);byte[] data = new byte[5];int len = 0;while ((len = in.read(data)) != -1) {arr.write(data, 0, len);}System.out.println(arr.toString());in.close();}}

8.StringReader和StringWriter
public class StringReader {public static void main(String[] args) throws Exception {BufferedReader reader2=new BufferedReader(new StringReader("黑马程序员"));StringWriter writer2=new StringWriter();writer2.append(reader2.readLine());writer2.append("------追加新文字");System.out.println(writer2.toString());BufferedReader reader3=new BufferedReader(new CharArrayReader("黑马程序员".toCharArray()));CharArrayWriter writer3=new CharArrayWriter();writer3.write(reader3.readLine().toCharArray());System.out.println(writer3.toString());}}

9.CharArrayReader和CharArrayWriter

public class CharArray {public static void main(String[] args) throws Exception {BufferedReader reader3=new BufferedReader(new CharArrayReader("黑马程序员".toCharArray()));CharArrayWriter writer3=new CharArrayWriter();writer3.write(reader3.readLine().toCharArray());System.out.println(writer3.toString());}}

总结:ByteArrayInputStream和ByteArrayOutputStream、CharArrayReader和CharArrayWriter、StringReader和StringWriter都是用流的思想操作内存中的数据。








0 0