Java IO流
Java IO流
Java IO简单介绍
概述
流是一组有顺序的,有起点和终点的字节集合,是对传输数据的总称或抽象。即数据在两设备间的传输称为流,流的本质是传输数据。依据传输数据特性将流抽象为各种类,方便更直观的进行数据操作。
- 依据处理数据类型的不同分为:字符流和字节流
- 依据数据流向不同分为:输入流和输出流
字符流和字节流
字符流的由来: 由于数据编码的不同,而有了对字符进行高效操作的流对象。本质事实上就是基于字节流读取时,去查了指定的码表。字节流和字符流的差别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,依据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理全部类型的数据(如图片、avi等),而字符流仅仅能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的。而字符流在操作的时候下后是会用到缓冲区的。是通过缓冲区来操作文件,我们将在以下验证这一点。
优先选用字节流。首先由于硬盘上的全部文件都是以字节的形式进行传输或者保存的,包含图片等内容。可是字符仅仅是在内存中才会形成的,所以在开发中,字节流使用广泛。
字符流类图示:
字节流类图示:
字符流
FileReader:
用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
要自己指定这些值,能够先在 FileInputStream 上构造一个 InputStreamReader。
FileReader 用于读取字符流。要读取原始字节流,能够考虑使用 FileInputStream。
/** * 此读入方式因为一次读一个字符,所以效率非常低 * 使用字符流读取一个文本文件,将读取到的文本内容打印到控制台。 */ public class Test { public static void main(String[] args) { FileReader fr = null; try { //指定读入流 fr = new FileReader("abc.txt"); int ch = 0; //推断是否读取到文件末尾 while ((ch = fr.read()) != -1) { System.out.println(ch); } } //捕获异常 catch (IOException e) { throw new RuntimeException("读取失败"); } finally { if (fr != null) { try { fr.close(); } catch (IOException e) { System.err.println("关闭失败"); } } } } }
/** * 此读入方式因为每次读入一块而非单个字符。所以效率高 * 使用字符流读取一个文本文件,将读取到的文本内容打印到控制台。 */ public class Test { public static void main(String[] args) { FileReader fr = null; try { //指定读入流 fr = new FileReader("abc.txt"); //指定一个缓冲区 char[] buf = new char[1024]; int len =0; //推断是否读取到文件末尾 while ((len = fr.read(buf)) != -1) { System.out.println(new String(buf, 0, len)); } } //捕获异常 catch (IOException e) { throw new RuntimeException("读取失败"); } finally { if (fr != null) { try { fr.close(); } catch (IOException e) { System.err.println("关闭失败"); } } } } }
FileWriter:
用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。
要自己指定这些值,能够先在 FileOutputStream 上构造一个 OutputStreamWriter。
文件是否可用或能否够被创建取决于底层平台。特别是某些平台一次仅仅同意一个 FileWriter(或其它文件写入对象)打开文件进行写入。在这样的情况下,假设所涉及的文件已经打开,则此类中的构造方法将失败。
FileWriter 用于写入字符流。
要写入原始字节流,能够考虑使用 FileOutputStream。
/** * 在磁盘上写一个文件。而且向文件里写入对应的字母。 * 对IO操作实现异常处理 */ public class Test { public static void main(String[] args) { // 指定一个输出源 FileWriter fw = null; try { fw = new FileWriter("d:\\abc.txt"); // 写入数据 fw.write("abcd"); } catch (IOException e) { // e.printStackTrace(); throw new RuntimeException("写入失败"); } finally { // 刷新并关闭资源 if (fw != null) { try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block System.out.println("关闭失败"); } } } } }
字符流复制一个文本文件。单个字节写入:
/** * 字符流复制一个文本文件 */ public class Test { public static void main(String[] args) { // 有一个读取源和写入源 FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("d:\\abc.txt"); fw = new FileWriter("d:\\abc_copy.txt"); // 不断读取而且写 int ch = 0; while ((ch = fr.read()) != -1) { fw.write(ch); } } catch (Exception e) { throw new RuntimeException("复制失败"); } finally { // 关闭流 if (fr != null) { try { fr.close(); } catch (IOException e) { System.out.println("关闭失败"); } } if (fw != null) { try { fw.close(); } catch (IOException e) { System.out.println("关闭失败"); } } } } }
文件复制(FileWriter和FileReader结合,字节数组缓冲方法读写):
/** * 字符流复制一个文本文件(高效方法、异常处理)。*/ public class Test { public static void main(String[] args) { // 读取源和写入源 FileReader fr = null; FileWriter fw = null; try { fr = new FileReader("d:\\abc.txt"); fw = new FileWriter("d:\\abc_copy.txt"); // 利用自己定义的缓存数组高效读写 char[] buf = new char[1024]; int len = 0; //推断是否读到文件末尾,若没有,则继续 while ((len = fr.read(buf)) != -1) { //一次写入一个缓冲块 fw.write(buf, 0, len); } } catch (Exception e) { throw new RuntimeException("复制失败"); } finally { // 推断读入流对象是否还存在。若存在则关闭 if (fr != null) { try { //关闭读入流 fr.close(); } catch (IOException e) { System.out.println("关闭失败"); } } //推断写出流对象是否还存在。若存在则关闭 if (fw != null) { try { //关闭写出流 fw.close(); } catch (IOException e) { System.out.println("关闭失败"); } } } } }
BufferedReader:
从字符输入流中读取文本。缓冲各个字符,从而实现字符、数组和行的高效读取。
能够指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
通常,Reader 所作的每一个读取请求都会导致对底层字符或字节流进行对应的读取请求。因此,建议用 BufferedReader 包装全部其 read() 操作可能开销非常高的 Reader(如 FileReader 和 InputStreamReader)。
比如。
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
将缓冲指定文件的输入。假设没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件里读取字节。并将其转换为字符后返回。而这是极其低效的。
通过用合适的 BufferedReader 替代每一个 DataInputStream,能够对将 DataInputStream 用于文字输入的程序进行本地化。
/** * 高效读取文本数据 */ public class Test { public static void main(String[] args) throws IOException { FileReader fr = null; BufferedReader bfr = null; try { //获取读入源 fr = new FileReader("abc.txt"); bfr = new BufferedReader(fr); String line = null; //循环将数据读入字符数组 while ((line = bfr.readLine()) != null) { System.out.println(line); } } catch (IOException e) { throw new RuntimeException("读取文件失败"); } finally { if (bfr != null) { try { //关闭流 bfr.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
BufferedWriter:
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
能够指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
该类提供了 newLine() 方法。它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。
并不是全部平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每一个输出行要优于直接写入新行符。
通常 Writer 将其输出马上发送究竟层字符或字节流。
除非要求提示输出。否则建议用 BufferedWriter 包装全部其 write() 操作可能开销非常高的 Writer(如 FileWriters 和 OutputStreamWriters)。比如,
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
将缓冲 PrintWriter 对文件的输出。
假设没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后马上写入到文件。而这是极其低效的。
/** * 字符流 copy文本文件 */ public class Test { private static int BUFFER_SIZE = 1024; public static void main(String[] args) throws IOException { copy_text(); } /* * 指定一个读取源 读取源是文本文件 * 指定一个写入目的 也是一个文件 文件名称能够和源读取文件不一样 * 频繁读取文本文件的内容 频繁的写入缓冲区 * 关闭而且刷新内容到目的地 */ public static void copy_text() { FileReader fr = null; FileWriter fw = null; BufferedReader bfr = null; BufferedWriter bfw = null; //定义源 try { //读取源 fr = new FileReader("d:\\abc.txt"); //高效读取 bfr = new BufferedReader(fr); //写入源 fw = new FileWriter("d:\\cc.txt"); //高效写入 bfw = new BufferedWriter(fw); //循环读写文件至末尾 String line = null; while ((line = bfr.readLine()) != null) { bfw.write(line); bfw.newLine(); bfw.flush(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { //关闭流 if (bfr != null) { try { bfr.close(); } catch (IOException e) { throw new RuntimeException("关闭失败"); } } if (bfw != null) { try { bfw.close(); } catch (IOException e) { throw new RuntimeException("关闭失败"); } } } } }
字节流
FileInputStream:
FileInputStream 从文件系统中的某个文件里获得输入字节。
FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,能够考虑使用 FileReader。
逐个字节读取文本文件:
/** * 字节流 * 读文件内容,节省空间 */ public class Test { public static void main(String[] args) throws IOException { //创建文件读取的文件对象 String fileName = "abc.txt"; File f = new File(fileName); //获取读入流 InputStream in = new FileInputStream(f); //获取文件字节大小。然后创建字节数组 (不适合过大文件的读取) byte[] b = new byte[(int) f.length()]; //循环读取字节 for (int i = 0; i < b.length; i++) { b[i] = (byte) in.read(); } if(in != null){ try { //关闭读取流对象 in.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println(new String(b)); } }
通过字节流数组缓冲,高效读取文本文件:
/** * 字节流 * 读文件内容,节省空间 */ public class Test { public static void main(String[] args) throws IOException { //创建文件读取的文件对象 String fileName = "abc.txt"; File f = new File(fileName); //获取读入流 InputStream in = new FileInputStream(f); //获取文件字节大小,然后创建字节数组 (不适合过大文件的读取) byte[] buf = new byte[1024]; //循环读取字节 int len = 0; //创建StringBuilder对象,用于连接读取后字符形成的字符串 StringBuilder sb = new StringBuilder(); while ((len = in.read(buf)) != -1) { sb.append(new String(buf, 0, len)); } if (in != null) { try { //关闭读取流对象 in.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println(sb.toString()); } }
FileOutputStream:
文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或是否能能够被创建取决于基础平台。特别是某些平台一次仅仅同意一个 FileOutputStream(或其它文件写入对象)打开文件进行写入。
在这样的情况下。假设所涉及的文件已经打开,则此类中的构造方法将失败。
FileOutputStream 用于写入诸如图像数据之类的原始字节的流。
要写入字符流,能够考虑使用 FileWriter。
逐个字节写出到文件:
public class Test { public static void main(String[] args) throws IOException { //定义写出的文件对象 String fileName ="hello.txt"; File f = new File(fileName); //获取写出流对象 OutputStream out = new FileOutputStream(f); //OutputStream out = new FileOutputStream(f,true); //以追加方式写入文件 String str = "Hello World!!"; //把字符串转成字节数组 byte[] b = str.getBytes(); //逐个字节写出到文件 for (int i = 0; i < b.length; i++) { out.write(b[i]); } //关闭写出流对象 out.close(); } }
通过字节数组写入到文件:
/** * 字节流 * */ import java.io.*; public class Test { public static void main(String[] args) throws IOException { //定义写出的文件对象 String fileName ="hello.txt"; File f = new File(fileName); //获取写出流对象 OutputStream out = new FileOutputStream(f); //OutputStream out = new FileOutputStream(f,true); //以追加方式写入文件 String str = "Hello World!!"; //把字符串转成字节数组 byte[] bytes = str.getBytes(); //通过写出流写出到文件 out.write(bytes); //关闭写出流对象 out.close(); } }
BufferedInputStream:
BufferedInputStream 为还有一个输入流加入一些功能。即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时。可依据须要从包括的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点。reset 操作使得在从包括的输入流中获取新字节之前。再次读取自最后一次 mark 操作后读取的全部字节。
BufferedOutputStream:
该类实现缓冲的输出流。通过设置这样的输出流。应用程序就能够将各个字节写入底层输出流中。而不必针对每次字节写入调用底层系统。
/* * 复制图片 */ public class Test { public static void copy_jpg() throws IOException { //定义图片读取源 FileInputStream fis = new FileInputStream("d:\\"); BufferedInputStream bfis = new BufferedInputStream(fis); //定义图片写入源 FileOutputStream fos = new FileOutputStream("d:\\1.mkv"); BufferedOutputStream bfos = new BufferedOutputStream(fos); //使用字节缓冲数组,高效读取 byte[] buf = new byte[1024]; int len = 0; while ((len = bfis.read(buf)) != -1) { bfos.write(buf, 0, len); //不须要这个刷新,查API文档可知这个flush方法中无有效运行代码 //bfos.flush(); } //关闭读入流 bfis.close(); //关闭写出流 bfos.close(); } }
InputStreamReader:
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集能够由名称指定或显式给定,或者能够接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,能够提前从底层流读取很多其它的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。比如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
/** * 将字节流转换为字符流 */ public class Test { public static void main(String[] args) throws IOException { //控制台输入 InputStream in = System.in; //将字节流转化为字符流 InputStreamReader isr = new InputStreamReader(in); int ch = 0; //循环读取 while ((ch = isr.read()) != -1) { System.out.print((char) ch); } isr.close(); } }
字符编码:
/** * 读取window创建的文件--当中有中文字符 */ public class Test { public static void main(String[] args) throws IOException { //使用字节流读取一个指定的文本文件 FileInputStream fis = new FileInputStream("d:\\b.txt"); //使用转换流将文本文件内容转换为字符流 转换时指定相应的字符集进行读取 InputStreamReader isr = new InputStreamReader(fis, "gbk"); //高效读取 BufferedReader bfr = new BufferedReader(isr); int ch = 0; //循环读取 while ((ch = isr.read()) != -1) { System.out.println((char) ch); } } }
OuputStreamWriter:
/** * 复制一个文本文件(指定读入写出编码) */ public class Test { public static void main(String[] args) throws IOException { //读取源文件 //转换并指定编码进行读取 //高效读取 BufferedReader bfr = new BufferedReader(new InputStreamReader(new FileInputStream("d:\\abc.txt"), "gbk")); //目标文件 //指定编码集进行写入 //高效写入 BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\\ccc.txt"), "gbk")); //循环读取而且写入目标文件 String line = null; while((line = bfr.readLine()) != null){ bfw.write(line); //写入换行符(因为bfw整行读取。不包含换行符。所以须要自己加入) bfw.newLine(); //刷新缓冲区 bfw.flush(); } //关闭流 bfr.close(); bfw.close(); } }
DataInputStream:
数据输入流同意应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序能够使用数据输出流写入稍后由数据输入流读取的数据。
public class Test { public static void main(String[] args) throws IOException { File file = new File("d:" + File.separator + "hello.txt"); //创建读入流对象input DataInputStream input = new DataInputStream(new FileInputStream(file)); char[] ch = new char[10]; int count = 0; char temp; //循环读取 while ((temp = input.readChar()) != 'C') { ch[count++] = temp; } System.out.println(ch); } }
DataOutputStream:
数据输出流同意应用程序以适当方式将基本 Java 数据类型写入输出流中。
然后。应用程序能够使用数据输入流将数据读入。
public class Test { public static void main(String[] args) throws IOException { //创建文件对象 File file = new File("d:" + File.separator + "hello.txt"); char[] ch = {'A', 'B', 'C'}; DataOutputStream out = null; //创建读入流对象 out = new DataOutputStream(new FileOutputStream(file)); for (char temp : ch) { //写入字符 out.writeChar(temp); } out.close(); } }
PushBackInputStream:
PushbackInputStream 为还有一个输入流加入性能,即“推回 (push back)”或“取消读取 (unread)”一个字节的能力。在代码片段能够非常方便地读取由特定字节值分隔的不定数量的数据字节时。这非常实用;在读取终止字节后,代码片段能够“取消读取”该字节,这样,输入流上的下一个读取操作将会又一次读取被推回的字节。比如,表示构成标识符字符的字节可能由表示操作符字符的字节终止。用于读取一个标识符的方法能够读取到遇到操作符为止。然后将该操作符推回以进行重读。
public class Test { public static void main(String[] args) throws IOException { String str = "hello,rollenholt"; PushbackInputStream push = null; ByteArrayInputStream bat = null; //创建ByteArrayInputStream读入流对象 bat = new ByteArrayInputStream(str.getBytes()); //创建PushbackInputStream读入流对象 push = new PushbackInputStream(bat); int temp = 0; while ((temp = push.read()) != -1) { if (temp == ',') { //推回 byte 数组的某一部分:将其拷贝到推回缓冲区之前。 push.unread(temp); //从此输入流中读取下一个数据字节 temp = push.read(); System.out.print("(回退" + (char) temp + ") "); } else { System.out.print((char) temp); } } } }
PipedInputStream:
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的全部数据字节。
通常,数据由某个线程从 PipedInputStream 对象读取,并由其它线程将其写入到对应的 PipedOutputStream。
不建议对这两个对象尝试使用单个线程,由于这样可能死锁线程。管道输入流包括一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。
假设向连接管道输出流提供数据字节的线程不再存在。则觉得该管道已损坏。
PipedOutputStream:
能够将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其它线程从连接的 PipedInputStream 读取。
不建议对这两个对象尝试使用单个线程,由于这样可能会造成该线程死锁。假设某个线程正从连接的管道输入流中读取数据字节。但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。
/** * 管道流 */ class Test { public static void main(String[] args) throws IOException { //创建发送对象 Send send = new Send(); //创建接收对象 Recive recive = new Recive(); try { //管道连接 send.getOut().connect(recive.getInput()); } catch (Exception e) { e.printStackTrace(); } new Thread(send).start(); new Thread(recive).start(); } } /** * 消息发送类 */ class Send implements Runnable { private PipedOutputStream out = null; //无參构造函数 public Send() { out = new PipedOutputStream(); } //获取管道写出流 public PipedOutputStream getOut() { return this.out; } @Override //重写Runnable接口的run()方法 public void run() { String message = "hello , Alice"; try { out.write(message.getBytes()); } catch (Exception e) { e.printStackTrace(); } try { //关闭写出流 out.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 接受消息类 */ class Recive implements Runnable { private PipedInputStream input = null; //无參构造函数 public Recive() { this.input = new PipedInputStream(); } //获取管道读入流对象 public PipedInputStream getInput() { return this.input; } @Override //重写Runnable接口的run()方法 public void run() { byte[] b = new byte[1000]; int len = 0; try { len = this.input.read(b); } catch (Exception e) { e.printStackTrace(); } try { //关闭读入流对象 input.close(); } catch (Exception e) { e.printStackTrace(); } System.out.println("接受的内容: " + (new String(b, 0, len))); } }
ZipOutputStream:
此类为以 ZIP 文件格式写入文件实现输出流过滤器。包含对已压缩和未压缩条目的支持。
/** * 创建压缩文件演示样例 */ public class Test { public static void main(String[] args) throws IOException { //创建压缩源文件对象 File file = new File("d:" + File.separator + "hello.txt"); //创建压缩文件对象 File zipFile = new File("d:" + File.separator + "hello.zip"); //创建源文件读入流对象 InputStream input = new FileInputStream(file); //创建压缩文件写出流对象 ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream( zipFile)); //開始写入新的 ZIP 文件条目并将流定位到条目数据的開始处 zipOut.putNextEntry(new ZipEntry(file.getName())); // 设置凝视 zipOut.setComment("hello"); int temp = 0; //循环写入字节 while ((temp = input.read()) != -1) { zipOut.write(temp); } //关闭读入流 input.close(); //关闭写出流 zipOut.close(); } }
ZipOutputStream类压缩多个文件:
public class Test { public static void main(String[] args) throws IOException { // 要被压缩的目录 File file = new File("d:" + File.separator + "temp"); File zipFile = new File("d:" + File.separator + "zipFile.zip"); InputStream input = null; ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream( zipFile)); zipOut.setComment("hello"); if (file.isDirectory()) { File[] files = file.listFiles(); for (int i = 0; i < files.length; ++i) { input = new FileInputStream(files[i]); zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + files[i].getName())); int temp = 0; while ((temp = input.read()) != -1) { zipOut.write(temp); } input.close(); } } zipOut.close(); } }
ZipInputStream类解压缩(包括多个文件的情况):
/** * 解压缩一个压缩文件里包括多个文件的情况 */ public class Test { public static void main(String[] args) throws IOException { File file = new File("d:" + File.separator + "zipFile.zip"); File outFile = null; ZipFile zipFile = new ZipFile(file); ZipInputStream zipInput = new ZipInputStream(new FileInputStream(file)); ZipEntry entry = null; InputStream input = null; OutputStream output = null; while ((entry = zipInput.getNextEntry()) != null) { System.out.println("解压缩" + entry.getName() + "文件"); outFile = new File("d:" + File.separator + entry.getName()); if (!outFile.getParentFile().exists()) { outFile.getParentFile().mkdir(); } if (!outFile.exists()) { outFile.createNewFile(); } input = zipFile.getInputStream(entry); output = new FileOutputStream(outFile); int temp = 0; while ((temp = input.read()) != -1) { output.write(temp); } input.close(); output.close(); } } }
SequenceInputStream:
SequenceInputStream 表示其它输入流的逻辑串联。它从输入流的有序集合開始。并从第一个输入流開始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包括的最后一个输入流的文件末尾为止。
/** * 文件合并 */ public class Test { public static void main(String[] args) throws IOException { //定义输出 FileOutputStream fos = new FileOutputStream("d:\\aaa\\d.txt"); //将一组流加入到list中 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); al.add(new FileInputStream("d:\\aaa\\a.txt")); al.add(new FileInputStream("d:\\aaa\\b.txt")); al.add(new FileInputStream("d:\\aaa\\c.txt")); //将list转换为Enumeration Enumeration<FileInputStream> en = Collections.enumeration(al); //创建序列流读入对象 SequenceInputStream sis = new SequenceInputStream(en); //创建缓冲字节数组 byte[] buf = new byte[1024]; int len = 0; //循环读取字节数据 while ((len = sis.read(buf)) != -1) { fos.write(buf, 0, len); } //关闭流 sis.close(); fos.close(); } }
/** * 文件分割 */ public class Test { public static void main(String[] args) throws IOException { splitFile(); } public static void splitFile() throws IOException { /* * 有一个较大源读取文件 * 创建读取的文件对象 */ File file = new File("d:\\aaa\\y.rmvb"); //创建读入流对象 FileInputStream fis = new FileInputStream(file); //创建写出流对象 FileOutputStream fos = null; //分割文件大小 byte[] buf = new byte[1024 * 1024 * 10]; int count = 0; int len = 0; //循环分割 while ((len = fis.read(buf)) != -1) { count++; //创建写出流 fos = new FileOutputStream(new File(file.getParent() + "\\" + count + ".part")); //写出数据 fos.write(buf, 0, len); //关闭写出流 fos.close(); } //关闭读入流 fis.close(); } }
ObjectInputStream& ObjectOutputStream:
ObjectInputStream 对曾经使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。
ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,能够为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些曾经序列化的对象。其它用途包含使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实參和形參。
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
能够使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件能够实现对象的持久存储。
假设流是网络套接字流,则能够在还有一台主机上或还有一个进程中重构对象。
将支持 java.io.Serializable 接口的对象写入流中。
每一个 serializable 对象的类都被编码,编码内容包含类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其它全部对象的闭包。
public class Test { public static void main(String[] args) throws IOException { //创建读入写出流对象 FileOutputStream outputStream = new FileOutputStream("hello.obj"); FileInputStream inputStream = new FileInputStream("hello.obj"); //创建对象读入写出流对象 ObjectOutputStream objOut = new ObjectOutputStream(outputStream); ObjectInputStream objIn = new ObjectInputStream(inputStream); //创建一个Person对象 Person person = new Person("Alice", 20); //把person对象写入对象流中 objOut.writeObject(person); //读入person对象 Person object = null; try { object = (Person) objIn.readObject(); } catch (ClassNotFoundException e) { e.printStackTrace(); } System.out.println(person.getName() + " : " + person.getAge()); } } //定义Person类。要想实现序列化。必须实现Serializable接口 class Person implements Serializable { //显示指定serialVersionUID,防止因为JDK版本号不正确而出现序列化操作失败的问题 private static final long serialVersionUID = 1L; private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
文件等
Properties:
Properties 类表示了一个持久的属性集。
Properties 可保存在流中或从流中载入。
属性列表中每一个键及其相应值都是一个字符串。
Properties配置文件:
/** * Properties配置存储为文件 */ public class Test { public static void main(String[] args) throws IOException{ Properties prop = new Properties(); prop.setProperty("zhangsan", "15000"); prop.setProperty("lisi", "8000"); prop.setProperty("wangwu", "20000"); //prop.list(System.out);//測试用 prop.store(new FileOutputStream("a.properties"), "configuration"); prop.setProperty("wangwu", "10000"); System.out.println(prop.getProperty("wangwu")); } }
/** * Properties */ public class Test { public static void main(String[] args) throws IOException { //获取系统配置信息 Properties properties = System.getProperties(); System.out.println(properties.toString()); //将配置打印信息到控制台 //list方法经经常使用来调试。当前配置中的所有配置 properties.list(System.out); //设置配置信息(自己定义的配置) Properties prop = new Properties(); prop.setProperty("zhangsan", "15000"); prop.setProperty("lisi", "18000"); prop.setProperty("wangwu", "8000"); prop.list(System.out); String s = prop.getProperty("lisi"); System.out.println(s); //获取所有配置信息(使用集合遍历) Set<String> props = prop.stringPropertyNames(); for (String key : props) { System.out.println(key + " -> " + prop.getProperty(key)); } //读取配置文件里的配置信息 Properties prop2 = new Properties(); //把配置信息输出到文件 FileInputStream is =new FileInputStream("salary.properties"); //载入文件里的配置信息到prop2中 prop2.load(is); String ss = prop2.getProperty("zhangsan"); System.out.println(ss); //控制台打印 prop2.list(System.out); } }
File基本属性
/** * File类的使用方法 */ public class Test { public static void main(String[] args) { //实例化对象时,文件不会产生 //File(String pathname) File file = new File("d:\\abc.txt"); File file1 = new File("d:\\"); //同一个分区的多个文件操作 多个分区的同一个文件 // File(String parent, String child) File file2 = new File("d:\\","abc.txt"); // File(File parent, String child) File path = new File("d:\\"); File file3 = new File(path,"abc.txt"); System.out.println(File.separator); // System.getProperty("file.separator") System.out.println(File.separatorChar); // System.getProperty("file.separator") System.out.println(System.getProperty("file.separator")); System.out.println(File.pathSeparator); // } }
/** * 打印一个文件的全部属性 */ public class Test { public static void main(String[] args) throws IOException { File file = new File("d:\\cd.txt"); System.out.println("getAbsolutePath = " + file.getAbsolutePath()); //绝对路径 System.out.println("getName=" + file.getName()); //文件名称 System.out.println("getCanonicalPath=" + file.getCanonicalPath()); //绝对路径的规范形式 System.out.println("getPath=" + file.getPath()); //定义文件路径时 内容是什么就打印什么 System.out.println("length=" + file.length()); //文件大小 System.out.println("lastModified=" + file.lastModified()); //最后改动时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); long t = file.lastModified(); String time = sdf.format(t); System.out.println(time); } }
文件分割与合并:
/** * 文件合并、文件分割、配置文件使用 */ public class Test { public static void main(String[] args) throws IOException { //指定须要分割的文件 File filein = new File("D:\\aaa\\y.rmvb"); //指定合并后的文件夹 File fileout = new File("D:\\bbb"); //切分 //split_file(filein); //合并 merge_file(new File(filein.getParent()), fileout); } /** * 合并文件 * * @param fileout :合并后的文件夹 * @param filein :合并前的文件夹 * @throws IOException */ public static void merge_file(File filein, File fileout) throws IOException { /* 获取配置文件信息*/ Properties prop = new Properties(); File[] propFiles = filein.listFiles(new MyFilenameFilter(".properties")); /*校验部分*/ if (propFiles.length != 1) { //此地默认切分生成文件夹中仅仅有一个配置文件 假设有多个配置文件 不予合并 throw new RuntimeException("配置文件不存在或者不唯一"); } //将取到的唯一的配置文件载入到Properties对象中 prop.load(new FileInputStream(propFiles[0])); //遍历并查找文件切分后的文件 File[] listFiles = filein.listFiles(new MyFilenameFilter(".part")); //推断文件个数是否等于切分时写入配置文件里的个数 if (listFiles.length != Integer.parseInt(prop.getProperty("filesplitnum"))) { throw new RuntimeException("文件缺失!"); } /*合并部分*/ //终于输出的文件名称 从配置文件里读取 合并到fileout中 FileOutputStream fos = new FileOutputStream(new File(fileout, prop.getProperty("filename"))); //定义一个容器 ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); for (File file : listFiles) { al.add(new FileInputStream(file)); } //将ArrayList中转换为Enumeration Enumeration<FileInputStream> en = Collections.enumeration(al); //使用序列流合并 SequenceInputStream sis = new SequenceInputStream(en); //開始合并 byte[] buf = new byte[1024]; int len = 0; while ((len = sis.read(buf)) != -1) { fos.write(buf, 0, len); } /* 资源释放部分*/ //关闭流 sis.close(); fos.close(); }
/** * 分割文件 * 參数一 file: 传递进来须要分割的文件 * * @throws IOException */ public static void split_file(File file) throws IOException { //读取原来的大文件 FileInputStream fis = new FileInputStream(file); //定义输出流 FileOutputStream fos = null; //获取须要分割的文件的所在路径 并将路径封装成为一个File对象 File path = new File(file.getParent()); byte[] buf = new byte[1024*1024 * 30]; int len = 0; int count = 0; while ((len = fis.read(buf)) != -1) { fos = new FileOutputStream(new File(path, (count++) + ".part")); fos.write(buf, 0, len); fos.close(); } //写配置文件 Properties prop = new Properties(); prop.setProperty("filename", file.getName()); prop.setProperty("filesplitnum", count + ""); //将配置对象存储到配置文件里 prop.store(new FileOutputStream(new File(path, file.getName() + ".properties")), "file split infos"); //关闭流 fis.close(); } }
文件过滤:
FilenameFilter:
FileFilter 是一个抽象类,JFileChooser 使用它过滤显示给用户的文件集合
FilenameFilter:
实现此接口的类实例可用于过滤器文件名称。Abstract Window Toolkit 的文件对话框组件使用这些实例过滤 File 类的 list 方法中的文件夹清单。
public class Test { public static void main(String[] args) { File file = new File("d:\\abc"); //通过过滤器过滤文件和文件夹。返回抽象路径名数组 String[] names = file.list(new MyFilenameFilter("d")); //遍历这些路径名字符串 for (String name : names) { System.out.println(name); } } } //实现自己的过滤器 public class MyFilenameFilter implements FilenameFilter { private String suffix; MyFilenameFilter(String suffix) { this.suffix = suffix; } @Override //重写父类accept方法。实现自己的过滤器 public boolean accept(File dir, String name) { return name.endsWith(suffix); } }
/** * 找出指定文件夹下的隐藏文件 和 指定文件扩展名文件 */ public class Test { public static void main(String[] args) { File file = new File("F:\\电影"); // 返回抽象路径名数组。这些路径名表示此抽象路径名表示的文件夹中满足指定过滤器的文件和文件夹。 File[] listFiles = file.listFiles(new MyFileFilter(".mkv")); //遍历这些文件对象 for (File f : listFiles) { System.out.println(f); } } } //自己的构造器类 class MyFileFilter implements FileFilter{ /* * 要隐藏文件 要指定扩展名 */ private String suffix; MyFileFilter(String suffix){ this.suffix = suffix; } @Override //重写父类的accept方法,实现自己的业务逻辑 public boolean accept(File pathname) { return pathname.getName().endsWith(suffix) && !pathname.isHidden(); } }
文件遍历:
/** * 深度遍历文件夹 */ public class Test { public static void main(String[] args) { File file = new File("D:\\a"); listAll_3(file, 0); } //加入文件夹缩进 public static void listAll_3(File file, int count) { System.out.println(addSpace(count) + file); //每调用一次加一次 count++; File[] listFiles = file.listFiles(); for (int i = 0; i < listFiles.length; i++) { //假设是文件夹 if (listFiles[i].isDirectory()) { listAll_3(listFiles[i], count); } else {//是文件 System.out.println(addSpace(count) + listFiles[i]); } } } //在文件夹前面加入空格 public static String addSpace(int count) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < count; i++) { sb.append("\t"); } return sb.toString(); }
/** * 列出文件夹中文件 */ public class Test { public static void main(String[] args) { File file = new File("D:\\abc"); //返回文件对象的文件夹下全部文件名的字符串 String[] list = file.list(); //遍历这些文件名字符串 for (String name : list) { //筛选出以.java结尾的文件 if (name.endsWith(".java")) { System.out.println(name); } } } }
/** * 获取指定文件夹下,指定扩展名的文件(包括子文件夹中的),将获取到的文件绝对路径依照关键词过滤。存储到UTF-8格式文本文件里。*/ public class Test { public static void main(String[] args) { //须要查找的路径 File path = new File("D:\\a"); File outpath = new File("D:\\aa.txt"); //定义一个容器 List<String> list = new ArrayList<String>(); //定义一个文件名称过滤器 MyFilenameFilter filter = new MyFilenameFilter(".txt"); //查找 findFiles(path, list, filter); //关键词 String suffix = "a"; //写结果集 writeFiles(list, outpath, suffix); } /** * 写结果集 * * @param list 结果集 * @param outpath 输出文件夹 * @param suffix 关键词 */ public static void writeFiles(List<String> list, File outpath, String suffix) { if (list.size() == 0) { return; } BufferedWriter bfw = null; try { //指定写入路径 bfw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outpath), "utf-8")); //遍历结果集 写 for (String path : list) { if (path.contains(suffix)) { bfw.write(path); bfw.newLine(); bfw.flush(); } } } catch (IOException e) { throw new RuntimeException("写入失败 error :" + e.toString()); } finally { //关闭流 if (bfw != null) { try { bfw.close(); } catch (IOException e) { e.printStackTrace(); } } } } /* * 找到符合条件的文件名称 * args:path为传递进来文件夹路径 * */ public static void findFiles(File path, List<String> list, MyFilenameFilter filter) { //推断传递进来的路径是否存在 if (!path.exists()) { return; } //依据条件进行过滤 File[] rsList = path.listFiles(); //文件夹下全部的内容查找出来 if (rsList.length > 0) { //遍历 for (File file : rsList) { if (file.isDirectory()) {//是文件夹 //递归 findFiles(file, list, filter); } else { //过滤文件扩展名 if (filter.accept(file, file.getName())) { list.add(file.getAbsolutePath()); } } } } } }
递归删除目录:
/** * 递归删除目录 */ public class Test { public static void main(String[] args) { File file = new File("D:\\aa"); deletedir(file); } public static void deletedir(File file) { //列出;路径下的文件及目录 File[] listFiles = file.listFiles(); //遍历删除 for(int i = 0 ; i < listFiles.length ; i++){ if(listFiles[i].isDirectory()){//假设是目录 deletedir(listFiles[i]); listFiles[i].delete(); }else{ //无论是目录或者是文件都尝试删一下 listFiles[i].delete(); } } //删除顶级目录 file.delete(); } }
/** * 实现创建并删除目录或者一个文件 */ public class Test { public static void main(String[] args) throws IOException { File file = new File("D:\\bbb.txt"); //文件创建 //创建一个新的文件 假设文件存在 不创建 boolean b = file.createNewFile(); //虚拟机退出时删除文件 file.deleteOnExit(); //创建不存在的一级目录 boolean b1 = file.mkdir(); //创建不存在的多级目录 boolean b2 = file.mkdirs(); //删除文件或目录,当目录非空。会出问题 boolean b3 = file.delete(); System.out.println(b); } }
控制台读入写出:
System.in:
/** * 读取键盘输入的数据 打印到控制台上 */ public class Test { public static void main(String[] args) throws IOException { //获取键盘输入的数据 InputStream in = System.in; int ch = 0; //循环读取输入的数据直到末尾 while ((ch = in.read()) != -1) { //将读取的字节流显示转化为字符 System.out.print((char) ch); } } }
System.out:
/** * 实现一个打印程序 */ public class Test { public static void main(String[] args) throws IOException { OutputStream out = System.out; out.write("abcd".getBytes()); } }
/** * 将用户输入的数据写入到文本文件里 */ public class Test { public static void main(String[] args) throws IOException { //输出目的源 FileOutputStream fos = new FileOutputStream("d:\\a.txt"); BufferedOutputStream bfos = new BufferedOutputStream(fos); //获取用户终端输入的数据 InputStream in = System.in; //使用高效读取 BufferedInputStream bin = new BufferedInputStream(in); int ch = 0; //循环读取字节 while ((ch = bin.read()) != -1) { bfos.write(ch); //刷新缓冲区 bfos.flush(); } } }
/** * 将文本文件里的内容打印到控制台上 */ public class Test { public static void main(String[] args)throws IOException { //读取源 FileInputStream fis =new FileInputStream("d:\\a.txt"); OutputStream out = System.out; int ch = 0; while ((ch = fis.read()) != -1) { out.write(ch); } fis.close(); } }
/** * 使用转换流实现输入字符转大写的打印功能 */ public class Test { public static void main(String[] args)throws IOException { read_console(); } public static void read_console()throws IOException { InputStream in = System.in; // 字节流转换为字符流 InputStreamReader isr =new InputStreamReader(in); BufferedReader bfr = new BufferedReader(isr); String line = null; while ((line = bfr.readLine()) !=null) { if ("exit".equals(line)) { return; } System.out.println(line.toUpperCase()); } isr.close(); bfr.close(); } }