1.IO系统读写文件工具类
1、文本文件读写工具类
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.BufferedReader;
4. import java.io.BufferedWriter;
5. import java.io.FileReader;
6. import java.io.FileWriter;
7. import java.io.IOException;
8.
9. /**
10. * 此工具类用于文本文件的读写
11. *
12. * @author Touch
13. */
14. public class TextFile {
15. // 读取指定路径文本文件
16. public static String read(String filePath) {
17. new StringBuilder();
18. null;
19. try {
20. new BufferedReader(new FileReader(filePath));
21. String s;
22. try {
23. while ((s = in.readLine()) != null)
24. '\n');
25. finally {
26. in.close();
27. }
28. catch (IOException e) {
29. // TODO Auto-generated catch block
30. e.printStackTrace();
31. }
32. return str.toString();
33. }
34.
35. // 写入指定的文本文件,append为true表示追加,false表示重头开始写,
36. //text是要写入的文本字符串,text为null时直接返回
37. public static void write(String filePath, boolean append, String text) {
38. if (text == null)
39. return;
40. try {
41. new BufferedWriter(new FileWriter(filePath,
42. append));
43. try {
44. out.write(text);
45. finally {
46. out.close();
47. }
48. catch (IOException e) {
49. // TODO Auto-generated catch block
50. e.printStackTrace();
51. }
52. }
53. }
54. </span>
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. public class TestTextFile {
4. public static void main(String[] args) {
5. "file/textfile.txt", false,
6. "这是一个文本文件的读写测试\nTouch\n刘海房\n男\n");
7. "file/textfile.txt", true, "武汉工业学院\n软件工程");
8. "file/textfile.txt"));
9. }
10. }
11. </span>
2、二进制文件读写工具类
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.BufferedInputStream;
4. import java.io.BufferedOutputStream;
5. import java.io.FileInputStream;
6. import java.io.FileOutputStream;
7. import java.io.IOException;
8.
9. /**
10. * 此工具类用于二进制文件的读写
11. *
12. * @author Touch
13. */
14. public class BinaryFile {
15. // 把二进制文件读入字节数组,如果没有内容,字节数组为null
16. public static byte[] read(String filePath) {
17. byte[] data = null;
18. try {
19. new BufferedInputStream(
20. new FileInputStream(filePath));
21. try {
22. new byte[in.available()];
23. in.read(data);
24. finally {
25. in.close();
26. }
27. catch (IOException e) {
28. e.printStackTrace();
29. }
30. return data;
31. }
32.
33. // 把字节数组为写入二进制文件,数组为null时直接返回
34. public static void write(String filePath, byte[] data) {
35. if (data == null)
36. return;
37. try {
38. new BufferedOutputStream(
39. new FileOutputStream(filePath));
40. try {
41. out.write(data);
42. finally {
43. out.close();
44. }
45. catch (IOException e) {
46. e.printStackTrace();
47. }
48. }
49. }
50. </span>
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.util.Arrays;
4.
5. public class TestBinaryFile {
6. public static void main(String[] args) {
7. "file/binaryfile.dat", new byte[] { 1, 2, 3, 4, 5, 6,
8. 7, 8, 9, 10, 'a', 'b', 'c' });
9. byte[] data = BinaryFile.read("file/binaryfile.dat");
10. System.out.println(Arrays.toString(data));
11. }
12. }
13. </span>
3、对象读写工具类(有问题,在读取多个对象时有问题,怎样把一个对象文件中的所有对象读出来?)
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.FileInputStream;
4. import java.io.FileOutputStream;
5. import java.io.IOException;
6. import java.io.ObjectInputStream;
7. import java.io.ObjectOutputStream;
8.
9. /**
10. * 此类用于对象的读写
11. *
12. * @author Touch
13. */
14. public class ObjectFile {
15. // 把一个对象写入文件,isAppend为true表示追加方式写,false表示重新写
16. public static void write(String filePath, Object o, boolean isAppend) {
17. if (o == null)
18. return;
19. try {
20. new ObjectOutputStream(
21. new FileOutputStream(filePath, isAppend));
22. try {
23. out.writeObject(o);
24. finally {
25. out.close();
26. }
27. catch (IOException e) {
28. e.printStackTrace();
29. }
30. }
31.
32. // 把一个对象数组写入文件,isAppend为true表示追加方式写,false表示重新写
33. public static void write(String filePath, Object[] objects, boolean isAppend) {
34. if (objects == null)
35. return;
36. try {
37. new ObjectOutputStream(
38. new FileOutputStream(filePath, isAppend));
39. try {
40. for (Object o : objects)
41. out.writeObject(o);
42. finally {
43. out.close();
44. }
45. catch (IOException e) {
46. e.printStackTrace();
47. }
48. }
49.
50. // 读取对象,返回一个对象
51. public static Object read(String filePath) {
52. null;
53. try {
54. new ObjectInputStream(new FileInputStream(
55. filePath));
56. try {
57. o = in.readObject();
58. finally {
59. in.close();
60. }
61. catch (Exception e) {
62. e.printStackTrace();
63. }
64. return o;
65. }
66.
67. // 读取对象,返回一个对象数组,count表示要读的对象的个数
68. public static Object[] read(String filePath, int count) {
69. new Object[count];
70. try {
71. new ObjectInputStream(new FileInputStream(
72. filePath));
73. try {
74. for (int i = 0; i < count; i++) {
75. //第二次调用in.readObject()就抛出异常,这是为什么?
76. objects[i] = in.readObject();
77. }
78. finally {
79. in.close();
80. }
81. catch (Exception e) {
82. e.printStackTrace();
83. }
84. return objects;
85. }
86. }
87. </span>
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.Serializable;
4.
5. public class TestObjectFile {
6. public static void main(String[] args) {
7. "file/object1", new Person(), false);
8. "file/object1", new Person(), true);
9. "file/object1", new Person[] { new Person("Touch", 1),
10. new Person("Rainbow", 0), new Person() }, true);
11. for (Object o : ObjectFile.read("file/object1", 5))
12. ((Person) o).display();
13. }
14. }
15.
16. class Person implements Serializable {
17. private String name = "刘海房";
18. private int sex = 0;
19.
20. int sex) {
21. this.name = name;
22. this.sex = sex;
23. }
24.
25. Person() {
26. }
27.
28. void display() {
29. "my name is :" + name);
30. 0) ? "男" : "女";
31. "性别:" + s);
32. }
33. }</span>
4、对象读写工具类(解决了3中的问题,能够写入及读取多个对象)
3中到底问题出在哪呢?先来看一段ObjectOutputStream构造方法的源代码,此源代码来自jdk1.6版。
[java] view plain copy
1. <span style="font-size:16px;"> public ObjectOutputStream(OutputStream out) throws IOException {
2. verifySubclass();
3. new BlockDataOutputStream(out);
4. new HandleTable(10, (float) 3.00);
5. new ReplaceTable(10, (float) 3.00);
6. false;
7. "font-size:16px;"><span style="color:#ff0000;">writeStreamHeader();
8. </span> bout.setBlockDataMode(true);
9. if (extendedDebugInfo) {
10. new DebugTraceInfoStack();
11. else {
12. null;
13. }
14. }</span>
这段代码中我们只需要关注writeStreamHeader();方法,这个方法在源代码中的解释是
[java] view plain copy
1. <span style="font-size:16px;"> /**
2. * The writeStreamHeader method is provided so subclasses can append or
3. * prepend their own header to the stream. It writes the magic number and
4. * version to the stream.
5. *
6. * @throws IOException if I/O errors occur while writing to the underlying
7. * stream
8. */</span>
也就是说我们打开(new)一个ObjectOutputStream的时候,这个ObjectOutputStream流中就已经被写入了一些信息,这些信息会写入到我们的文件中。在第一次写入文件时,这些头部信息时需要的,因为ObjectInputStream读的时候会帮我们过滤掉。但是当我们追加写入一个文件时,这些头部信息也会写入文件中,读取的时候只会把文件第一次出现的头部信息过滤掉,并不会把文件中间的头部信息也过滤掉,这就是问题的根源所在。
lichong_87提到的
一、可以在每次写入的时候把文件中所有对象读出来,然后重新写入,这种方法效率比较低。
writeStreamHeader();方法中写入的,所以我们可以通过继承ObjectOutputStream来覆盖这个方法,如果不是第一次写入文件,这个方法什么也不做。
下面是第二种解决方案的源代码及测试
[java] view plain copy
1. <span style="font-size:16px;">package mine.util.io;
2.
3. import java.io.File;
4. import java.io.IOException;
5. import java.io.ObjectOutputStream;
6. import java.io.OutputStream;
7.
8. /**
9. * 此类继承ObjectOutputStream,重写writeStreamHeader()方法,以实现追加写入时去掉头部信息
10. */
11. public class MyObjectOutputStream extends ObjectOutputStream {
12. private static File f;
13.
14. // writeStreamHeader()方法是在ObjectOutputStream的构造方法里调用的
15. // 由于覆盖后的writeStreamHeader()方法用到了f。如果直接用此构造方法创建
16. // 一个MyObjectOutputStream对象,那么writeStreamHeader()中的f是空指针
17. // 因为f还没有初始化。所以这里采用单态模式
18. private MyObjectOutputStream(OutputStream out, File f) throws IOException,
19. SecurityException {
20. super(out);
21. }
22.
23. // 返回一个MyObjectOutputStream对象,这里保证了new MyObjectOutputStream(out, f)
24. // 之前f已经指向一个File对象
25. public static MyObjectOutputStream newInstance(File file, OutputStream out)
26. throws IOException {
27. // 本方法最重要的地方:构建文件对象,两个引用指向同一个文件对象
28. return new MyObjectOutputStream(out, f);
29. }
30.
31. @Override
32. protected void writeStreamHeader() throws IOException {
33. // 文件不存在或文件为空,此时是第一次写入文件,所以要把头部信息写入。
34. if (!f.exists() || (f.exists() && f.length() == 0)) {
35. super.writeStreamHeader();
36. else {
37. // 不需要做任何事情
38. }
39. }
40. }
41. </span>
[java] view plain copy
1. <span style="font-size:16px;">package mine.util.io;
2.
3. import java.io.File;
4. import java.io.FileInputStream;
5. import java.io.FileOutputStream;
6. import java.io.IOException;
7. import java.io.ObjectInputStream;
8.
9. /**
10. * 此类用于对象的读写
11. *
12. * @author Touch
13. */
14. public class ObjectFile {
15. // 把一个对象写入文件,isAppend为true表示追加方式写,false表示重新写
16. public static void write(String filePath, Object o, boolean isAppend) {
17. if (o == null)
18. return;
19. try {
20. new File(filePath);
21. MyObjectOutputStream out = MyObjectOutputStream.newInstance(f,
22. new FileOutputStream(f, isAppend));
23. try {
24. out.writeObject(o);
25. finally {
26. out.close();
27. }
28. catch (IOException e) {
29. e.printStackTrace();
30. }
31. }
32.
33. // 把一个对象数组写入文件,isAppend为true表示追加方式写,false表示重新写
34. public static void write(String filePath, Object[] objects, boolean isAppend) {
35. if (objects == null)
36. return;
37. try {
38. new File(filePath);
39. MyObjectOutputStream out = MyObjectOutputStream.newInstance(f,
40. new FileOutputStream(f, isAppend));
41. try {
42. for (Object o : objects)
43. out.writeObject(o);
44. finally {
45. out.close();
46. }
47. catch (IOException e) {
48. e.printStackTrace();
49. }
50. }
51.
52. // 读取对象,返回一个对象
53. public static Object read(String filePath) {
54. null;
55. try {
56. new ObjectInputStream(new FileInputStream(
57. filePath));
58. try {
59. o = in.readObject();
60. finally {
61. in.close();
62. }
63. catch (Exception e) {
64. e.printStackTrace();
65. }
66. return o;
67. }
68.
69. // 读取对象,返回一个对象数组,count表示要读的对象的个数
70. public static Object[] read(String filePath, int count) {
71. new Object[count];
72. try {
73. new ObjectInputStream(new FileInputStream(
74. filePath));
75. try {
76. for (int i = 0; i < count; i++) {
77.
78. objects[i] = in.readObject();
79. }
80. finally {
81. in.close();
82. }
83. catch (Exception e) {
84. e.printStackTrace();
85. }
86. return objects;
87. }
88. }
89. </span>
[java] view plain copy
1. <span style="font-size:16px;">package mine.util.io;
2.
3. import java.io.Serializable;
4.
5. public class TestObjectFile {
6. public static void main(String[] args) {
7. "file/t.dat", new Person(), false);
8. "file/t.dat", new Person(), true);
9. "file/t.dat", new Person[] { new Person("Touch", 1),
10. new Person("Rainbow", 0), new Person() }, true);
11. for (Object o : ObjectFile.read("file/t.dat", 5))
12. ((Person) o).display();
13. }
14. }
15.
16. class Person implements Serializable {
17. private static final long serialVersionUID = 1L;
18. private String name = "刘海房";
19. private int sex = 0;
20.
21. int sex) {
22. this.name = name;
23. this.sex = sex;
24. }
25.
26. Person() {
27. }
28.
29. void display() {
30. "my name is :" + name);
31. 0) ? "男" : "女";
32. "性别:" + s);
33. }
34. }</span>
运行结果:
my name is :刘海房
性别:男
my name is :刘海房
性别:男
my name is :Touch
性别:女
my name is :Rainbow
性别:男
my name is :刘海房
性别:男
2.IO系统File类及文件搜索工具类
1、先看一个File类的简单的例子
[java] view plain copy
1. <span style="font-size:16px;">package test;
2.
3. import java.io.File;
4. import java.io.FilenameFilter;
5. import java.util.Arrays;
6. import java.util.Scanner;
7. import java.util.regex.Pattern;
8.
9. /**
10. * File代表文件和目录,静态域有:与系统有关的路径分隔符、与系统有关的默认名称分隔符。
11. * 主要操作有:创建文件或目录、删除文件、给文件设定属性、返回指定目录下的文件列表、
12. * 返回过滤后的文件列表、 检测文件是否存在、是否隐藏、是否是目录还是文件、
13. * 返回文件名称和路径
14. *
15. * @author Touch
16. *
17. */
18. public class FileDemo {
19. /*
20. * 查找指定路径下的匹配regex的文件
21. */
22. public String[] find(String path, final String regex) {
23. new File(path);
24. //匿名内部类
25. return file.list(new FilenameFilter() {
26. private Pattern pattern = Pattern.compile(regex);
27. @Override
28. public boolean accept(File dir, String name) {
29. // TODO Auto-generated method stub
30. return pattern.matcher(name).matches();
31. }
32. });
33. }
34.
35. public static void main(String[] args) {
36. null;
37. null;
38. null;
39. int choice = 1;
40. new Scanner(System.in);
41. "please input the file path:");
42. path = scanner.next();
43. "please input key:");
44. key = scanner.next();
45. "choise:\n0:匹配以" + key + "为后缀的文件\n1:匹配包含" + key
46. "的文件");
47. if ((choice = scanner.nextInt()) == 0)
48. ".*\\." + key;
49. else
50. ".*" + key + ".*";
51. String[] list;
52. new FileDemo().find(path, regex);
53. System.out.println(Arrays.deepToString(list));
54. //返回指定路径下的目录列表
55. new File(path).listFiles();
56. for (File file : fileList) {
57. if (file.isDirectory()) {
58. new FileDemo().find(file.getPath(), regex);
59. System.out.println(Arrays.deepToString(list));
60. }
61. }
62. }
63.
64. }
65. </span>
2、看完这个例子,是不是可以写个工具类呢,用于搜索指定路径下的所有文件或者目录,当然也可以输入正则表达式,这样就可以筛选出我们想要的文件(如有时候我们只需要.java文件或者.txt文件)
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.File;
4. import java.util.ArrayList;
5. import java.util.List;
6.
7. /**
8. * FileDirectory类用于查找指定根目录下的所有文件和目录 可以通过正则表达式对要查找的 文件及目录进行筛选
9. *
10. * @author Touch
11. */
12. public final class SearchFile {
13. // 存放文件
14. private List<File> fileList = new ArrayList<File>();
15. // 存放目录
16. private List<File> directoryList = new ArrayList<File>();
17. // 存放文件和目录
18. private List<File> list = new ArrayList<File>();
19. private File file;// 目录
20. private String regex;// 正则表达式
21.
22. public SearchFile(String path) {
23. new File(path);
24. this.regex = ".*";
25. }
26.
27. public SearchFile(File file) {
28. this.file = file;
29. this.regex = ".*";
30. }
31.
32. public SearchFile(String path, String regex) {
33. new File(path);
34. this.regex = regex;
35. }
36.
37. public SearchFile(File file, String regex) {
38. this.file = file;
39. this.regex = regex;
40. }
41.
42. // 返回当前目录下的所有文件及子目录
43. public List<File> files() {
44. File[] files = file.listFiles();
45. new ArrayList<File>();
46. for (File f : files)
47. if (f.getName().matches(regex))
48. list.add(f);
49. return list;
50. }
51.
52. // 返回该根目录下的所有文件
53. public List<File> allFiles() {
54. if (list.isEmpty())
55. search(file);
56. return fileList;
57. }
58.
59. // 返回该根目录下的所有子目录
60. public List<File> allDirectory() {
61. if (list.isEmpty())
62. search(file);
63. return directoryList;
64. }
65.
66. // 返回该根目录下的所有文件及子目录
67. public List<File> allFilesAndDirectory() {
68. if (list.isEmpty())
69. search(file);
70. return list;
71. }
72.
73. // 递归搜索当前目录下的所有文件及目录
74. private void search(File file) {
75. File[] files = file.listFiles();
76. if (files == null || files.length == 0)
77. return;
78. for (File f : files) {
79. if (f.getName().matches(regex))
80. list.add(f);
81. if (f.isFile() && f.getName().matches(regex))
82. fileList.add(f);
83. else {
84. if (f.getName().matches(regex))
85. directoryList.add(f);
86. search(f);
87. }
88. }
89. }
90. }
91. </span>
3、测试
[java] view plain copy
1. <span style="font-size:16px;">package mine.util;
2.
3. import java.io.File;
4. import java.util.List;
5.
6. public class TestSearchFile {
7. public static void main(String[] args) {
8. "-------- 指定目录中所有文件及子目录-------");
9. new SearchFile(
10. "G:/java/workspace/test/file").files();
11. for (File file : list)
12. System.out.println(file.getName());
13. "--------指定目录中以txt为后缀的文件------");
14. new SearchFile("G:/java/workspace/test/file",
15. ".*\\.txt").files();
16. for (File file : list)
17. System.out.println(file.getName());
18. "--------以该目录为根目录的所有文件及子目录--");
19. new SearchFile("G:/java/workspace/test")
20. .allFilesAndDirectory();
21. for (File file : list)
22. System.out.println(file.getName());
23. }
24. }
25. </span>
4、结果:
-------- 指定目录中所有文件及子目录-------
aa.data
bb.dat
object
test.txt
test1.txt
test2.txt
test3.txt
test4.txt
test5
--------指定目录中以txt为后缀的文件------
test.txt
test1.txt
test2.txt
test3.txt
test4.txt
--------以该目录为根目录的所有文件及子目录--
.classpath
.project
.settings
org.eclipse.jdt.core.prefs
bin
http
PassWord.class
Test.class
mine
util
SearchFile.class
TestSearchFile.class
test
A.class
ArraysDemo.class
B.class
ByteArrayInputStreamDemo.class
DataInputStreamAndByteArrayInputStreamDemo.class
DataInputStreamDemo.class
DeepCloneDemo.class
FileDemo$1.class
FileDemo.class
FileInputStreamDemo.class